Set-up

Loading packages & custom functions

library(readr)
library(dplyr)
library(metafor)
library(devtools)
library(purrr)
library(tidyverse)
library(tidyr)
library(tibble)
library(kableExtra)
library(robumeta)
library(ggpubr)
library(ggplot2)
library(here)

Functions for preparing the data for meta analyses

  1. Create function for sub-setting the data to choose only one data point per individual per trait: “data_subset_parameterid_individual_by_age”
data_subset_parameterid_individual_by_age <- function(mydata, parameter, age_min=0, age_center=100) {
  tmp <- mydata %>%
    filter(
      age_in_days >= age_min,
      id == parameter
    ) %>%
    # take results for single individual closest to age_center
    mutate(age_diff = abs(age_center - age_in_days)) %>%
    group_by(biological_sample_id) %>%
    filter(age_diff == min(age_diff)) %>%
    select(-age_diff)# %>% 
#    filter(!duplicated(biological_sample_id))
    
  # still some individuals with multiple records (because same individual appear under different procedures, so filter to one record)
  j <- match(unique(tmp$biological_sample_id), tmp$biological_sample_id)
  tmp[j, ] 
  }
  1. “Population statistics”: “calculate_population_stats” This function groups animals from the same strain and same insitiution together. This is done for each trait seoarately, and only for traits that have been measured in both sexes. Any group containing fewer than 5 individuals is excluded.
calculate_population_stats <- function(mydata, min_individuals = 5) {
  mydata %>%
    group_by(population, strain_name, production_center, sex) %>%
    summarise(
      trait = parameter_name[1],
      x_bar = mean(data_point),
      x_sd = sd(data_point),
      n_ind = n()
    ) %>%
    ungroup() %>%
    filter(n_ind > min_individuals) %>%
    # Check both sexes present & filter those missing
    group_by(population) %>%
    mutate(
      n_sex = n_distinct(sex)
    ) %>%
    ungroup() %>%
    filter(n_sex == 2) %>%
    select(-n_sex) %>%
    arrange(production_center, strain_name, population, sex)
}
  1. Extraction of effect sizes and sample variances: “create_meta_analysis_effect_sizes”
create_meta_analysis_effect_sizes <- function(mydata) {
  i <- seq(1, nrow(mydata), by = 2)
  input <- data.frame(
    n1i = mydata$n_ind[i],
    n2i = mydata$n_ind[i + 1],
    x1i = mydata$x_bar[i],
    x2i = mydata$x_bar[i + 1],
    sd1i = mydata$x_sd[i],
    sd2i = mydata$x_sd[i + 1]
  )

  mydata[i, ] %>%
    select(strain_name, production_center, trait) %>%
    mutate(
      effect_size_CVR = calculate_lnCVR(CMean = input$x1i, CSD = input$sd1i, CN = input$n1i, EMean = input$x2i, ESD = input$sd2i, EN = input$n2i),
      sample_variance_CVR = calculate_var_lnCVR(CMean = input$x1i, CSD = input$sd1i, CN = input$n1i, EMean = input$x2i, ESD = input$sd2i, EN = input$n2i),
      effect_size_VR = calculate_lnVR(CSD = input$sd1i, CN = input$n1i, ESD = input$sd2i, EN = input$n2i),
      sample_variance_VR = calculate_var_lnVR(CN = input$n1i, EN = input$n2i),
      effect_size_RR = calculate_lnRR(CMean = input$x1i, CSD = input$sd1i, CN = input$n1i, EMean = input$x2i, ESD = input$sd2i, EN = input$n2i),
      sample_variance_RR = calculate_var_lnRR(CMean = input$x1i, CSD = input$sd1i, CN = input$n1i, EMean = input$x2i, ESD = input$sd2i, EN = input$n2i),
      err = as.factor(seq_len(n()))
    )
}
  1. Calculate meta-analysis statistics

Based on function created by A M Senior @ the University of Otago NZ 03/01/2014:

  • Calculates effect sizes for meta-analysis of variance. All functions take the mean, sd and n from the control and experimental groups.
  • The first function, calculate_lnCVR, calculates the the log response-ratio of the coefficient of variance (lnCVR) - see Nakagawa et al 2015.
  • The second function calculates the measurement error variance for lnCVR. As well as the aforementioned parameters, this function also takes Equal_E_C_Corr (default = T), which must be True or False. If true, the function assumes that the correlation between mean and sd (Taylor’s Law) is equal for the mean and control groups, and, thus these data are pooled. If False the mean-SD correlation for the experimental and control groups are calculated separately from one another.
  • Similar functions are then implemented for lnVR (for comparison of standard deviations) and ln RR (for comparison of means)

calculate_lnCVR <- function(CMean, CSD, CN, EMean, ESD, EN) {
  log(ESD) - log(EMean) + 1 / (2 * (EN - 1)) - (log(CSD) - log(CMean) + 1 / (2 * (CN - 1)))
}

calculate_var_lnCVR <- function(CMean, CSD, CN, EMean, ESD, EN, Equal_E_C_Corr = T) {
  if (Equal_E_C_Corr == T) {
    mvcorr <- 0 # cor.test(log(c(CMean, EMean)), log(c(CSD, ESD)))$estimate   old, slightly incorrect
    S2 <- CSD^2 / (CN * (CMean^2)) + 1 / (2 * (CN - 1)) - 2 * mvcorr * sqrt((CSD^2 / (CN * (CMean^2))) * (1 / (2 * (CN - 1)))) + ESD^2 / (EN * (EMean^2)) + 1 / (2 * (EN - 1)) - 2 * mvcorr * sqrt((ESD^2 / (EN * (EMean^2))) * (1 / (2 * (EN - 1))))
  }
  else {
    Cmvcorr <- cor.test(log(CMean), log(CSD))$estimate
    Emvcorr <- cor.test(log(EMean), (ESD))$estimate
    S2 <- CSD^2 / (CN * (CMean^2)) + 1 / (2 * (CN - 1)) - 2 * Cmvcorr * sqrt((CSD^2 / (CN * (CMean^2))) * (1 / (2 * (CN - 1)))) + ESD^2 / (EN * (EMean^2)) + 1 / (2 * (EN - 1)) - 2 * Emvcorr * sqrt((ESD^2 / (EN * (EMean^2))) * (1 / (2 * (EN - 1))))
  }
  S2
}

calculate_lnVR <- function(CSD, CN, ESD, EN) {
  log(ESD) - log(CSD) + 1 / (2 * (EN - 1)) - 1 / (2 * (CN - 1))
}

calculate_var_lnVR <- function(CN, EN) {
  1 / (2 * (EN - 1)) + 1 / (2 * (CN - 1))
}

calculate_lnRR <- function(CMean, CSD, CN, EMean, ESD, EN) {
  log(EMean) - log(CMean)
}

calculate_var_lnRR <- function(CMean, CSD, CN, EMean, ESD, EN) {
  CSD^2 / (CN * CMean^2) + ESD^2 / (EN * EMean^2)
}

Load & clean data

  1. Data loading and cleaning of the csv file

This step we have already done and provide a cleaned up file which is less computing intensive and which we have saved in a folder called export. However, the cvs is provided in case this is preferred to be attempted, following the steps below:

# loads the raw data, setting some default types for various columns

load_raw <- function(filename) {
  read_csv(filename,
    col_types = cols(
      .default = col_character(),
      project_id = col_character(),
      id = col_character(),
      parameter_id = col_character(),
      age_in_days = col_integer(),
      date_of_experiment = col_datetime(format = ""),
      weight = col_double(),
      phenotyping_center_id = col_character(),
      production_center_id = col_character(),
      weight_date = col_datetime(format = ""),
      date_of_birth = col_datetime(format = ""),
      procedure_id = col_character(),
      pipeline_id = col_character(),
      biological_sample_id = col_character(),
      biological_model_id = col_character(),
      weight_days_old = col_integer(),
      datasource_id = col_character(),
      experiment_id = col_character(),
      data_point = col_double(),
      age_in_weeks = col_integer(),
      `_version_` = col_character()
    )
  )
}

# Apply some standard cleaning to the data
clean_raw_data <- function(mydata) {
  
  group <- read_csv(here("data", "ParameterGrouping.csv"))
  
  tmp <- 
    mydata %>%

    # Filter to IMPC source (recommend by Jeremey in email to Susi on 20 Aug 2018)
    filter(datasource_name == "IMPC") %>%

    # standardise trait names
    mutate(parameter_name = tolower(parameter_name)) %>%

    # remove extreme ages
    filter(age_in_days > 0 & age_in_days < 500) %>%

    # remove NAs
    filter(!is.na(data_point)) %>%

    # subset to reasonable set of variables, date_of_experiment used as an indicator of batch-level effects
    select(production_center, strain_name, strain_accession_id, biological_sample_id, pipeline_stable_id, procedure_group, procedure_name, sex, date_of_experiment, age_in_days, weight, parameter_name, data_point) %>% 

    # sort
    arrange(production_center, biological_sample_id, age_in_days)
      
    # filter to groups with > 1 centre  
    merge(tmp, 
          tmp %>% group_by(parameter_name) %>%
    summarise(center_per_trait = length(unique(production_center, na.rm = TRUE)))
        )%>%
    filter(center_per_trait >= 2) %>% 

    # Define population variable
    mutate(population = sprintf("%s-%s", production_center, strain_name)) %>% 

    # add grouping variable: these were decided based on functional groups and procedures 
    mutate(parameter_group = group$parameter[match(parameter_name, group$parameter_name)] ) %>%
    
    # Assign unique IDs (per trait)
    # each unique parameter_name (=trait,use trait variable) gets a unique number ('id')

    # We add a new variable, where redundant traits are combined
    #[note however, at this stage the dataset still contains nonsensical traits, i.e. traits that may not contain any information on variance]
    mutate(id = match(parameter_name, unique(parameter_name))) %>% 
    as_tibble()
}

# Load raw data - save cleaned dataset as RDS for reuse
data_raw <- load_raw(here("data","dr7.0_all_control_data.csv.gz"))
dir.create("export", F, F)

data <- data_raw %>% 
  clean_raw_data() 
saveRDS(data, "export/data_clean.rds")

For analysis we load the RDS created above and other datasets:

data <- readRDS(here("export", "data_clean.rds")) 

procedures <- read_csv(here("data", "procedures.csv"))
Parsed with column specification:
cols(
  procedure = col_character(),
  GroupingTerm = col_character()
)

Checking length of different variables and sample sizes.

Table 1: “Strains and Center Sample Sizes”

This table summarises the available numbers of male and female mice from each strain and originating institution.

length(unique(data$parameter_name)) # 232 traits
[1] 232
length(unique(data$parameter_group)) # 161 parameter groups
[1] 161
length(unique(data$procedure_name)) # 26 procedure groups
[1] 26
length(unique(data$biological_sample_id)) # 27147 individial mice   
[1] 27147
#number of males and females per strain per production center 
kable(cbind(data %>% group_by(production_center, strain_name) %>% count(biological_sample_id, sex) %>% count(sex) %>% print(n = Inf))) %>%
  kable_styling() %>%
  scroll_box(width = "60%", height = "200px")
production_center strain_name sex n
BCM C57BL/6N female 653
BCM C57BL/6N male 639
BCM C57BL/6N;C57BL/6NTac female 47
BCM C57BL/6N;C57BL/6NTac male 52
BCM C57BL/6NCrl female 4
BCM C57BL/6NCrl male 2
BCM C57BL/6NJ female 6
BCM C57BL/6NJ male 6
BCM C57BL/6NTac female 1
BCM C57BL/6NTac male 5
HMGU C57BL/6NCrl female 313
HMGU C57BL/6NCrl male 311
HMGU C57BL/6NTac female 1045
HMGU C57BL/6NTac male 1062
ICS C57BL/6N female 1025
ICS C57BL/6N male 1050
JAX C57BL/6NJ female 2025
JAX C57BL/6NJ male 2022
KMPC C57BL/6N;C57BL/6NTac female 271
KMPC C57BL/6N;C57BL/6NTac male 266
MARC C57BL/6N female 936
MARC C57BL/6N male 926
MRC Harwell C57BL/6NTac female 2639
MRC Harwell C57BL/6NTac male 2661
MRC Harwell C57BL/6NTac no_data 3
RBRC C57BL/6NJcl female 222
RBRC C57BL/6NJcl male 222
RBRC C57BL/6NTac female 526
RBRC C57BL/6NTac male 523
TCP C57BL/6NCrl female 552
TCP C57BL/6NCrl male 524
TCP C57BL6/NCrl female 2
TCP C57BL6/NCrl male 2
UC Davis C57BL/6N male 1
UC Davis C57BL/6NCrl female 1155
UC Davis C57BL/6NCrl male 1158
WTSI B6Brd;B6Dnk;B6N-Tyr<c-Brd> female 97
WTSI B6Brd;B6Dnk;B6N-Tyr<c-Brd> male 87
WTSI C57BL/6J-Tyr<c-Brd> or C57BL/6NTac/USA male 3
WTSI C57BL/6N female 1951
WTSI C57BL/6N male 2008
WTSI C57BL/6N;C57BL/6NTac female 41
WTSI C57BL/6N;C57BL/6NTac male 7
WTSI C57BL/6NCrl male 13
WTSI C57BL/6NTac female 49
WTSI C57BL/6NTac male 34

Meta-analyses

1. Population as analysis unit

(Step C, Figure 3 in main document)

Loop: Meta-analyses on all traits

  • The loop combines the functions mentioned above and fills the data matrix with results from our meta analysis.
  • Error messages indicate traits that either did not reach convergence, or that did not return meaningful results in the meta-analysis, due to absence of variance. Those traits will be removed in later steps, outlined below.

(n <- length(unique(data$id)))
[1] 232
# Create dataframe to store results
results_alltraits_grouping <- 
    tibble(id = 1:n, lnCVR=0, lnCVR_lower=0, lnCVR_upper=0, 
           lnCVR_se=0, lnVR=0, lnVR_lower=0, lnVR_upper=0, 
           lnVR_se=0, lnRR=0, lnRR_lower=0, lnRR_upper=0, lnRR_se=0, sampleSize=0, trait=0)

for (t in 1:n) {
  tryCatch(
    {
      results <- data %>% 
        data_subset_parameterid_individual_by_age(t) %>%
        calculate_population_stats() %>%
        create_meta_analysis_effect_sizes()

      # lnCVR,  log repsonse-ratio of the coefficient of variance
      cvr <- metafor::rma.mv(yi = effect_size_CVR, V = sample_variance_CVR, 
                             random = list(~ 1 | strain_name, ~ 1 | production_center, ~ 1 | err), 
                             control = list(optimizer = "optim", optmethod = "Nelder-Mead", 
                                            maxit = 1000), verbose = F, data = results)

      # lnVR, comparison of standard deviations
      cv <- metafor::rma.mv(yi = effect_size_VR, V = sample_variance_VR,
                            random = list(~ 1 | strain_name, ~ 1 | production_center, ~ 1 | err), 
                            control = list(optimizer = "optim", optmethod = "Nelder-Mead", 
                                           maxit = 1000), verbose = F, data = results)

      # for means, lnRR
      means <- metafor::rma.mv(yi = effect_size_RR, V = sample_variance_RR, 
                               random = list(~ 1 | strain_name, ~ 1 | production_center, ~ 1 | err), 
                               control = list(optimizer = "optim", optmethod = "Nelder-Mead", 
                                              maxit = 1000), verbose = F, data = results)
      
      f <- function(x) unlist(x[c("b", "ci.lb", "ci.ub", "se")])

      results_alltraits_grouping[t, 2:14] <- c(f(cvr), f(cv), f(means), means$k)
      results_alltraits_grouping[t, 15] <- unique(results$trait)
    },
    error = function(e) {
      cat("ERROR :", t, conditionMessage(e), "\n")
    }
  )
}
ERROR : 84 Optimizer (optim) did not achieve convergence (convergence = 10). 
Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.There are outcomes with non-positive sampling variances.'V' appears to be not positive definite.
ERROR : 158 Optimizer (optim) did not achieve convergence (convergence = 10). 
Rows with NAs omitted from model fitting.
ERROR : 160 NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.
ERROR : 161 NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.
ERROR : 162 NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.
ERROR : 163 NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.
ERROR : 165 NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.
ERROR : 166 NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.There are outcomes with non-positive sampling variances.'V' appears to be not positive definite.Rows with NAs omitted from model fitting.
ERROR : 168 NA/NaN/Inf in 'y' 
Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.There are outcomes with non-positive sampling variances.'V' appears to be not positive definite.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.There are outcomes with non-positive sampling variances.'V' appears to be not positive definite.Rows with NAs omitted from model fitting.
ERROR : 231 NA/NaN/Inf in 'y' 

In the above function, we use ‘tryCatch’ and ‘conditionMessage’ to prevent the loop from aborting when the first error at row 84 is produced. As convergence in the two listed non-converging cases can’t be achieved by sensibly tweaking (other optim etc.), and we only learn about non-convergence in the loop, it is not possible to exclude the traits (N=2) beforehand. Similarly, there are 8 traits with very low variation, which can not be excluded prior running the loop.

The produced “Warnings” indicate cases where variance components are set to zero during likelihood optimization.

Merging datasets & removal of non-converged traits

Procedure names, grouping variables and trait names (“parameter_names”) are merged back together with the results from the metafor analysis above.

results_alltraits_grouping2 <- 
  results_alltraits_grouping %>% 
  left_join(by="id",
             data %>% select(id, parameter_group, procedure = procedure_name, procedure_name, parameter_name) %>%   # We filter duplicated id's to get only one unique row per id (and there is one id per parameter_name)
              filter(!duplicated(id))
            ) %>%
  # Below we add 'procedure' (from the previously loaded 'procedures.csv') as a variable
  left_join(by="procedure", 
            procedures %>% distinct()
            )
  

(n <- length(unique(results_alltraits_grouping2$parameter_name))) # 232
[1] 232

Removal of traits

14 traits from the originally 232 that had been included are removed because they either did not achieve convergence or are nonsensical for analysis of variance (such as traits that show no variation, see list below).

Not converged: “dp t cells”, “mzb (cd21/35 high)”

Not enough variation: “number of caudal vertebrae”, “number of cervical vertebrae”, “number of digits”, “number of lumbar vertebrae”, “number of pelvic vertebrae”, “number of ribs left”,“number of ribs right”, “number of signals”, “number of thoracic vertebrae”, “total number of acquired events in panel a”,“total number of acquired events in panel b”, “whole arena permanence”.

# We exclude 14 parameter names for which metafor models didn't converge ("dp t cells", "mzb (cd21/35 high)"), and of parameters that don't harbour enough variation
meta_clean <- results_alltraits_grouping2 %>% 
      filter(!parameter_name %in% c("dp t cells", "mzb (cd21/35 high)", "number of caudal vertebrae", 
      "number of cervical vertebrae", "number of digits", "number of lumbar vertebrae", "number of pelvic vertebrae", "number of ribs left",                       
        "number of ribs right", "number of signals", "number of thoracic vertebrae", "total number of acquired events in panel a",
        "total number of acquired events in panel b", "whole arena permanence"))

Reveiw: check against old script – identical, remove once fixed # #Felix: not sure

meta_clean.test <- readRDS(here("export", "meta_clean.test.rds"))  
all.equal(meta_clean, meta_clean.test %>% mutate(id=as.integer(id), parameter_group = as.character(parameter_group), GroupingTerm = as.character(GroupingTerm)))

[1] “Rows in x but not y: 162, 161. Rows in y but not x: 162, 161.” Not sure??

2. Meta-analysis: condensing non-independent traits

(Step F in Figure 3 in main article)

Dealing with Correlated Parameters, preparation

This dataset contained a number of highly correlated traits, such as different kinds of cell counts (for example hierarchical parameterization within immunological assays). As those data-points are not independent of each other, we conducted meta analyses on these correlated parameters to collapse the number of levels.

Collapsing and merging correlated parameters

Here we double check numbers of trait parameters in the dataset


meta1 <- meta_clean 
length(unique(meta1$procedure)) #18
[1] 18
length(unique(meta1$GroupingTerm)) #9
[1] 9
length(unique(meta1$parameter_group)) # 148 levels. To be used as grouping factor for meta-meta analysis / collapsing down based on things that are classified identically in "parameter_group" but have different "parameter_name"
[1] 148
length(unique(meta1$parameter_name)) #218
[1] 218

Count of number of parameter names (correlated sub-traits) in each parameter group (par_group_size)

Table: Numbers of correlated and uncorrelated traits

This serves to identify and separate the traits that are correlated from the full dataset that can be processed as is. If the sample size (n) for a given “parameter group” equals 1, the trait is unique and uncorrelated. All instances, where there are 2 or more traits associated with the same parameter group (90 cases), are selected for a “mini-meta analysis”, which removes the issue of correlation.

kable(cbind(meta1 %>% count(parameter_group))) %>%
  kable_styling() %>%
  scroll_box(width = "60%", height = "200px")
parameter_group n
12khz-evoked abr threshold 1
18khz-evoked abr threshold 1
24khz-evoked abr threshold 1
30khz-evoked abr threshold 1
6khz-evoked abr threshold 1
alanine aminotransferase 1
albumin 1
alkaline phosphatase 1
alpha-amylase 1
area under glucose response curve 1
aspartate aminotransferase 1
B cells 4
basophil cell count 1
basophil differential count 1
bmc/body weight 1
body length 1
body temp 1
body weight 1
body weight after experiment 1
body weight before experiment 1
bone area 1
bone mineral content (excluding skull) 1
bone mineral density (excluding skull) 1
calcium 1
cardiac output 1
cd4 nkt 6
cd4 t 7
cd8 nkt 6
cd8 t 7
cdcs 2
center average speed 1
center distance travelled 1
center permanence time 1
center resting time 1
chloride 1
click-evoked abr threshold 1
creatine kinase 1
creatinine 1
cv 1
distance travelled - total 1
dn nkt 6
dn t 7
ejection fraction 1
end-diastolic diameter 1
end-systolic diameter 1
eosinophils 3
fasted blood glucose concentration 1
fat mass 1
fat/body weight 1
follicular b cells 2
forelimb and hindlimb grip strength measurement mean 1
forelimb grip strength measurement mean 1
fractional shortening 1
free fatty acids 1
fructosamine 1
glucose 1
hdl-cholesterol 1
heart weight 1
heart weight normalised against body weight 1
hematocrit 1
hemoglobin 1
hr 1
hrv 1
initial response to glucose challenge 1
insulin 1
iron 1
lactate dehydrogenase 1
latency to center entry 1
ldl-cholesterol 1
lean mass 1
lean/body weight 1
left anterior chamber depth 1
left corneal thickness 1
left inner nuclear layer 1
left outer nuclear layer 1
left posterior chamber depth 1
left total retinal thickness 1
locomotor activity 1
luc 2
lvawd 1
lvaws 1
lvidd 1
lvids 1
lvpwd 1
lvpws 1
lymphocytes 2
magnesium 1
mean cell hemoglobin concentration 1
mean cell volume 1
mean corpuscular hemoglobin 1
mean platelet volume 1
mean r amplitude 1
mean sr amplitude 1
monocytes 3
neutrophils 3
nk cells 6
nkt cells 4
number of center entries 1
number of rears - total 1
others 1
pdcs 1
percentage center time 1
percentage of live gated events 2
periphery average speed 1
periphery distance travelled 1
periphery permanence time 1
periphery resting time 1
phosphorus 1
platelet count 1
pnn5(6>ms) 1
potassium 1
pq 1
pr 1
pre-pulse inhibition 5
qrs 1
qtc 1
qtc dispersion 1
red blood cell count 1
red blood cell distribution width 1
respiration rate 1
respiratory exchange ratio 1
response amplitude 10
right anterior chamber depth 1
right corneal thickness 1
right inner nuclear layer 1
right outer nuclear layer 1
right posterior chamber depth 1
right total retinal thickness 1
rmssd 1
rp macrophage (cd19- cd11c-) 1
rr 1
sodium 1
spleen weight 1
st 1
stroke volume 1
t cells 3
tibia length 1
total bilirubin 1
total cholesterol 1
total food intake 1
total protein 1
total water intake 1
triglycerides 1
urea (blood urea nitrogen - bun) 1
uric acid 1
white blood cell count 1
whole arena average speed 1
whole arena resting time 1
meta1_sub <- meta1 %>%
  # add summary of number of parameter names in each parameter group
  group_by(parameter_group) %>%
  mutate(par_group_size = length(unique(parameter_name)), 
         sampleSize = as.numeric(sampleSize)) %>% 
  ungroup() %>% 
  # Create subsets with > 1 count (par_group_size > 1)
  filter(par_group_size > 1) # 90 observations

Meta-analyses on correlated (sub-)traits, using robumeta`

Here we pepare the subset of the data (using nest()), and in this first step the model of the meta analysis effect sizes are calculated


meta1b <-
  meta1 %>%
  group_by(parameter_group) %>% 
  summarize(par_group_size = length(unique(parameter_name, na.rm = TRUE)))
#this gives a summary of number of parameter names in each parameter group, now it neeeds to get merged it back together


meta1$par_group_size <- meta1b$par_group_size[match(meta1$parameter_group, meta1b$parameter_group)]

# Create subsets with > 1 count (par_group_size > 1) 

meta1_sub <- subset(meta1,par_group_size >1) # 90 observations   
meta1_sub$sampleSize <- as.numeric(meta1_sub$sampleSize)

# nesting
n_count <- meta1_sub %>%
  group_by(parameter_group) %>%
  mutate(raw_N = sum(sampleSize)) %>%
  nest() %>%
  ungroup()

model_count <- n_count %>%
  mutate(
    model_lnRR = map(data, ~ robu(.x$lnRR ~ 1, data = .x, studynum = .x$id, modelweights = c("CORR"), rho = 0.8, small = TRUE, var.eff.size = (.x$lnRR_se)^2)),
    model_lnVR = map(data, ~ robu(.x$lnVR ~ 1, data = .x, studynum = .x$id, modelweights = c("CORR"), rho = 0.8, small = TRUE, var.eff.size = (.x$lnVR_se)^2)),
    model_lnCVR = map(data, ~ robu(.x$lnCVR ~ 1, data = .x, studynum = .x$id, modelweights = c("CORR"), rho = 0.8, small = TRUE, var.eff.size = (.x$lnCVR_se)^2))
  )

Extract and save parameter estimates:

Function to collect the outcomes of the “mini” meta analysis

count_fun <- function(mod_sub) {
  return(c(mod_sub$reg_table$b.r, mod_sub$reg_table$CI.L, mod_sub$reg_table$CI.U, mod_sub$reg_table$SE))
} # estimate, lower ci, upper ci, SE

Extraction of values created during Meta analysis using robu meta:

robusub_RR <- model_count %>%
  transmute(parameter_group, estimatelnRR = map(model_lnRR, count_fun)) %>%
  mutate(r = map(estimatelnRR, ~ data.frame(t(.)))) %>%
  unnest(r) %>%
  select(-estimatelnRR) %>%
  purrr::set_names(c("parameter_group", "lnRR", "lnRR_lower", "lnRR_upper", "lnRR_se"))

robusub_CVR <- model_count %>%
  transmute(parameter_group, estimatelnCVR = map(model_lnCVR, count_fun)) %>%
  mutate(r = map(estimatelnCVR, ~ data.frame(t(.)))) %>%
  unnest(r) %>%
  select(-estimatelnCVR) %>%
  purrr::set_names(c("parameter_group", "lnCVR", "lnCVR_lower", "lnCVR_upper", "lnCVR_se"))

robusub_VR <- model_count %>%
  transmute(parameter_group, estimatelnVR = map(model_lnVR, count_fun)) %>%
  mutate(r = map(estimatelnVR, ~ data.frame(t(.)))) %>%
  unnest(r) %>%
  select(-estimatelnVR) %>%
  purrr::set_names(c("parameter_group", "lnVR", "lnVR_lower", "lnVR_upper", "lnVR_se"))

robu_all <- full_join(robusub_CVR, robusub_VR) %>% full_join(., robusub_RR)
Joining, by = "parameter_group"
Joining, by = "parameter_group"

Combine data

Merge the two data sets (the new [robu_all] and the initial [uncorrelated sub-traits with count = 1])

meta_all <- meta1 %>%
  filter(par_group_size == 1) %>%
  as_tibble()
# str(meta_all)
# str(robu_all)
# which(is.na(match(names(meta_all),names(robu_all))))  # check

#Step1:  Columns are matched by name (in our case, 'parameter_group'), and any missing columns will be filled with NA
combinedmeta <- bind_rows(robu_all, meta_all)
# glimpse(combinedmeta)

# Steps 2&3 (add information about number of traits in a parameter group, procedure, and grouping term) 
metacombo <- combinedmeta
metacombo$counts <- meta1$par_group_size[match(metacombo$parameter_group, meta1$parameter_group)] 
metacombo$procedure2 <- meta1$procedure[match(metacombo$parameter_group, meta1$parameter_group)]
metacombo$GroupingTerm2 <- meta1$GroupingTerm[match(metacombo$parameter_group, meta1$parameter_group)]

Clean-up, reorder, and rename

metacombo <- metacombo[c("parameter_group", "counts","procedure2","GroupingTerm2", "lnCVR","lnCVR_lower","lnCVR_upper","lnCVR_se","lnVR","lnVR_lower","lnVR_upper","lnVR_se","lnRR","lnRR_lower","lnRR_upper","lnRR_se")] 

names(metacombo)[names(metacombo)=="procedure2"] <- "procedure" 
names(metacombo)[names(metacombo)=="GroupingTerm2"] <- "GroupingTerm" 

# Quick pre-check before doing plots
metacombo %>%
  group_by(GroupingTerm) %>%
  dplyr::summarize(MeanCVR = mean(lnCVR), MeanVR = mean(lnVR), MeanRR = mean(lnRR))

Table for SHINY APP

We use this corrected (for correlated traits) “results” table, which contains each of the meta-analytic means for all effect sizes of interest, for further analyses. We further use this table as part of the Shiny App, which is able to provide the percentage differences between males and females for mean, variance and coefficient of variance.

This is the full result dataset

kable(metacombo) %>%
  kable_styling() %>%
  scroll_box(width = "100%", height = "200px")

parameter_group counts procedure GroupingTerm lnCVR lnCVR_lower lnCVR_upper lnCVR_se lnVR lnVR_lower lnVR_upper lnVR_se lnRR lnRR_lower lnRR_upper lnRR_se
pre-pulse inhibition 5 Acoustic Startle and Pre-pulse Inhibition (PPI) Behaviour 0.0232963 -0.0802563 0.1268488 0.0370507 0.0091028 -0.0364640 0.0546695 0.0143431 -0.0052156 -0.0427126 0.0322815 0.0128092
B cells 4 Immunophenotyping Immunology -0.0938959 -0.2500020 0.0622103 0.0426972 -0.0995337 -0.2068001 0.0077328 0.0250132 -0.0026281 -0.1298230 0.1245668 0.0393018
cd4 nkt 6 Immunophenotyping Immunology -0.0287688 -0.0566987 -0.0008389 0.0101634 -0.2018746 -0.3102294 -0.0935198 0.0331161 -0.2344450 -0.4005266 -0.0683635 0.0633501
cd4 t 7 Immunophenotyping Immunology -0.1507387 -0.2427976 -0.0586798 0.0360690 -0.1699213 -0.2629450 -0.0768975 0.0348324 -0.0031242 -0.0411564 0.0349081 0.0148989
cd8 nkt 6 Immunophenotyping Immunology -0.0424402 -0.0782046 -0.0066759 0.0119223 -0.0300442 -0.1823594 0.1222710 0.0533765 0.0035372 -0.0573749 0.0644494 0.0205272
cd8 t 7 Immunophenotyping Immunology -0.1223681 -0.2179976 -0.0267387 0.0358727 -0.1581698 -0.2342579 -0.0820816 0.0270229 -0.0415806 -0.0510391 -0.0321221 0.0023119
cdcs 2 Immunophenotyping Immunology -0.0362947 -0.3588637 0.2862742 0.0253867 0.1080248 -0.0565718 0.2726213 0.0129540 0.1642541 -0.1701520 0.4986601 0.0263183
dn nkt 6 Immunophenotyping Immunology -0.0619371 -0.1359380 0.0120637 0.0257746 -0.1572129 -0.2814342 -0.0329915 0.0447163 -0.1727105 -0.2906356 -0.0547854 0.0441034
dn t 7 Immunophenotyping Immunology -0.0796127 -0.1844481 0.0252227 0.0420063 -0.2421038 -0.3431678 -0.1410397 0.0406314 -0.2298147 -0.2519708 -0.2076586 0.0072373
eosinophils 3 Hematology Hematology -0.0662225 -0.2806631 0.1482181 0.0325859 -0.0154112 -0.4051652 0.3743427 0.0865366 -0.0042422 -0.2409206 0.2324362 0.0508093
follicular b cells 2 Immunophenotyping Immunology -0.1160077 -0.7256692 0.4936538 0.0479814 -0.1050194 -0.6946364 0.4845977 0.0464039 0.0052427 -0.1872381 0.1977236 0.0151486
luc 2 Hematology Hematology 0.0180436 -0.2038464 0.2399336 0.0174631 0.2657035 -1.2251358 1.7565428 0.1173316 0.2215497 -1.4136389 1.8567382 0.1286921
lymphocytes 2 Hematology Hematology 0.0805230 -2.2618128 2.4228588 0.1843458 0.1550159 -1.0892706 1.3993024 0.0979275 0.0602144 -1.0131287 1.1335576 0.0844739
monocytes 3 Hematology Hematology -0.0214677 -0.2033706 0.1604352 0.0420605 0.0784876 -0.1811005 0.3380757 0.0585593 0.1025193 -0.1483375 0.3533762 0.0571438
neutrophils 3 Hematology Hematology 0.2587446 0.0130803 0.5044089 0.0557516 0.3799805 -0.2060446 0.9660057 0.1317980 0.1319372 -0.2669324 0.5308068 0.0924336
nk cells 6 Immunophenotyping Immunology -0.0414772 -0.0960406 0.0130862 0.0200411 0.0156533 -0.0703789 0.1016856 0.0315487 0.0471757 -0.0162213 0.1105728 0.0231831
nkt cells 4 Immunophenotyping Immunology 0.0033757 -0.1069890 0.1137404 0.0294661 -0.2458705 -0.4452333 -0.0465077 0.0426738 -0.1823355 -0.3233946 -0.0412763 0.0314580
percentage of live gated events 2 Immunophenotyping Immunology -0.0934933 -0.3037340 0.1167473 0.0165463 -0.0412606 -0.1414443 0.0589231 0.0078846 0.0500941 0.0081191 0.0920690 0.0033035
response amplitude 10 Acoustic Startle and Pre-pulse Inhibition (PPI) Behaviour 0.0333147 -0.0127585 0.0793879 0.0202947 0.2549274 0.1969787 0.3128761 0.0255003 0.2016062 0.1108136 0.2923987 0.0401164
t cells 3 Immunophenotyping Immunology -0.1338701 -0.2750284 0.0072883 0.0326594 -0.1240786 -0.4120104 0.1638531 0.0668611 -0.0005749 -0.1663201 0.1651702 0.0374233
12khz-evoked abr threshold 1 Auditory Brain Stem Response Hearing 0.0538655 -0.0056830 0.1134139 0.0303824 0.0869649 0.0065802 0.1673497 0.0410134 0.0024851 -0.0214504 0.0264205 0.0122122
18khz-evoked abr threshold 1 Auditory Brain Stem Response Hearing 0.0238241 -0.0331809 0.0808292 0.0290848 0.0250266 -0.0488450 0.0988982 0.0376903 -0.0200763 -0.0431508 0.0029982 0.0117729
24khz-evoked abr threshold 1 Auditory Brain Stem Response Hearing 0.0518127 -0.0148242 0.1184497 0.0339991 -0.0891510 -0.3321998 0.1538977 0.1240067 -0.0224536 -0.0444163 -0.0004910 0.0112057
30khz-evoked abr threshold 1 Auditory Brain Stem Response Hearing 0.0170933 -0.0533187 0.0875053 0.0359252 -0.0344797 -0.1017901 0.0328306 0.0343426 -0.0497874 -0.0748197 -0.0247550 0.0127718
6khz-evoked abr threshold 1 Auditory Brain Stem Response Hearing -0.0077678 -0.0418582 0.0263226 0.0173934 0.0141682 -0.0189973 0.0473337 0.0169215 0.0184043 0.0056897 0.0311189 0.0064872
alanine aminotransferase 1 Clinical Chemistry Physiology -0.0684217 -0.1895020 0.0526586 0.0617768 0.0585179 -0.1322507 0.2492866 0.0973327 0.1069442 0.0319934 0.1818950 0.0382409
albumin 1 Clinical Chemistry Physiology 0.1133080 0.0451475 0.1814685 0.0347764 0.0559995 -0.0080678 0.1200668 0.0326880 -0.0567840 -0.0732083 -0.0403597 0.0083799
alkaline phosphatase 1 Clinical Chemistry Physiology 0.1043649 0.0451585 0.1635713 0.0302079 -0.3112471 -0.3980164 -0.2244778 0.0442709 -0.4216032 -0.4694832 -0.3737231 0.0244290
alpha-amylase 1 Clinical Chemistry Physiology 0.0383407 -0.0423419 0.1190232 0.0411653 0.2795566 0.1615777 0.3975355 0.0601944 0.2246987 0.1793151 0.2700822 0.0231553
area under glucose response curve 1 Intraperitoneal glucose tolerance test (IPGTT) Metabolism -0.1531723 -0.2210551 -0.0852895 0.0346347 0.2748396 0.1950895 0.3545898 0.0406896 0.4357738 0.3655882 0.5059595 0.0358097
aspartate aminotransferase 1 Clinical Chemistry Physiology 0.0119165 -0.1228287 0.1466617 0.0687488 -0.0566968 -0.2457779 0.1323843 0.0964717 -0.0585577 -0.1331777 0.0160624 0.0380722
basophil cell count 1 Hematology Hematology -0.0917931 -0.2022487 0.0186624 0.0563559 0.2031265 -0.0131549 0.4194079 0.1103497 0.2675772 0.0643028 0.4708516 0.1037133
basophil differential count 1 Hematology Hematology -0.0934739 -0.1787512 -0.0081966 0.0435096 -0.0639511 -0.2828066 0.1549044 0.1116630 -0.0156339 -0.1102310 0.0789633 0.0482647
bmc/body weight 1 Body Composition (DEXA lean/fat) Morphology 0.1314998 0.0329846 0.2300151 0.0502638 -0.0448684 -0.1340146 0.0442777 0.0454836 -0.1722378 -0.2207030 -0.1237726 0.0247276
body length 1 Body Composition (DEXA lean/fat) Morphology -0.0347988 -0.0824528 0.0128552 0.0243137 -0.0059677 -0.0526221 0.0406866 0.0238037 0.0282722 0.0233254 0.0332189 0.0025239
body temp 1 Echo Heart -0.0325368 -0.1066429 0.0415693 0.0378099 -0.0303742 -0.1044537 0.0437054 0.0377964 0.0018532 -0.0005002 0.0042066 0.0012008
body weight 1 Body Weight Morphology 0.0245675 -0.0420402 0.0911752 0.0339841 0.2335793 0.1694979 0.2976607 0.0326952 0.2096770 0.1938727 0.2254813 0.0080636
body weight after experiment 1 Indirect Calorimetry Metabolism 0.0853708 0.0299665 0.1407751 0.0282680 0.2849370 0.2328875 0.3369866 0.0265564 0.2030973 0.1864076 0.2197871 0.0085153
body weight before experiment 1 Indirect Calorimetry Metabolism 0.1053511 0.0412461 0.1694562 0.0327073 0.3038998 0.2435428 0.3642568 0.0307949 0.2008638 0.1816362 0.2200914 0.0098102
bone area 1 Body Composition (DEXA lean/fat) Morphology 0.0981587 0.0272824 0.1690349 0.0361620 0.1286546 0.0533659 0.2039432 0.0384133 0.0315241 0.0003806 0.0626676 0.0158898
bone mineral content (excluding skull) 1 Body Composition (DEXA lean/fat) Morphology 0.1709230 0.0625642 0.2792818 0.0552861 0.2091372 0.1015600 0.3167143 0.0548873 0.0372537 -0.0130828 0.0875902 0.0256824
bone mineral density (excluding skull) 1 Body Composition (DEXA lean/fat) Morphology 0.0542638 -0.0881612 0.1966887 0.0726671 0.0492830 -0.1087868 0.2073528 0.0806494 0.0012286 -0.0187942 0.0212514 0.0102159
calcium 1 Clinical Chemistry Physiology 0.0097946 -0.0464600 0.0660492 0.0287018 0.0135683 -0.0424600 0.0695966 0.0285864 0.0036564 -0.0000609 0.0073737 0.0018966
cardiac output 1 Echo Heart 0.0133816 -0.0797535 0.1065166 0.0475188 0.1017991 0.0206287 0.1829694 0.0414142 0.0934439 0.0580233 0.1288645 0.0180721
center average speed 1 Open Field Behaviour 0.0167300 -0.0404735 0.0739335 0.0291860 -0.0588515 -0.1004209 -0.0172820 0.0212093 -0.0724619 -0.1149622 -0.0299616 0.0216842
center distance travelled 1 Open Field Behaviour -0.0162603 -0.0733243 0.0408038 0.0291149 -0.1060637 -0.2023343 -0.0097930 0.0491186 -0.0940204 -0.1945774 0.0065366 0.0513055
center permanence time 1 Open Field Behaviour -0.0253715 -0.0826435 0.0319004 0.0292209 -0.0255734 -0.1014389 0.0502922 0.0387076 -0.0035151 -0.0902886 0.0832585 0.0442730
center resting time 1 Open Field Behaviour 0.0244492 -0.0737922 0.1226906 0.0501241 -0.0228690 -0.1548339 0.1090960 0.0673303 -0.0630751 -0.2215457 0.0953955 0.0808538
chloride 1 Clinical Chemistry Physiology 0.0321555 -0.1270972 0.1914083 0.0812529 0.0241491 -0.1438502 0.1921485 0.0857155 -0.0127047 -0.0177349 -0.0076745 0.0025665
click-evoked abr threshold 1 Auditory Brain Stem Response Hearing -0.0529450 -0.1534816 0.0475915 0.0512951 -0.0561198 -0.1827679 0.0705282 0.0646176 -0.0154221 -0.0577200 0.0268757 0.0215809
creatine kinase 1 Clinical Chemistry Physiology 0.0241232 -0.1071457 0.1553920 0.0669751 -0.1318792 -0.3968974 0.1331390 0.1352159 -0.1344413 -0.3838303 0.1149476 0.1272416
creatinine 1 Clinical Chemistry Physiology 0.0352315 -0.0229205 0.0933835 0.0296699 0.1066373 -0.2200831 0.4333578 0.1666972 -0.0844078 -0.1320251 -0.0367905 0.0242950
cv 1 Electrocardiogram (ECG) Heart 0.1874544 0.0716631 0.3032457 0.0590783 -0.0895722 -0.2484833 0.0693388 0.0810786 -0.2401301 -0.3410322 -0.1392280 0.0514816
distance travelled - total 1 Open Field Behaviour -0.0187819 -0.0858957 0.0483318 0.0342423 -0.1272582 -0.1997426 -0.0547738 0.0369825 -0.1121373 -0.1816322 -0.0426424 0.0354572
ejection fraction 1 Echo Heart -0.0300111 -0.1345066 0.0744844 0.0533150 -0.0525735 -0.1483174 0.0431705 0.0488499 -0.0284086 -0.0492579 -0.0075592 0.0106376
end-diastolic diameter 1 Echo Heart 0.1120972 0.0431489 0.1810454 0.0351783 0.1743929 0.0875252 0.2612607 0.0443211 0.0600907 0.0354923 0.0846891 0.0125504
end-systolic diameter 1 Echo Heart -0.0084176 -0.0780811 0.0612459 0.0355433 0.0668966 -0.0016692 0.1354624 0.0349832 0.0763195 0.0451136 0.1075254 0.0159217
fasted blood glucose concentration 1 Intraperitoneal glucose tolerance test (IPGTT) Metabolism -0.0177245 -0.1256855 0.0902366 0.0550832 0.0702824 -0.0302439 0.1708087 0.0512899 0.0868420 0.0493007 0.1243832 0.0191541
fat mass 1 Body Composition (DEXA lean/fat) Morphology 0.0408799 -0.0430149 0.1247746 0.0428042 0.3714313 0.2698790 0.4729837 0.0518134 0.3282080 0.2669032 0.3895129 0.0312786
fat/body weight 1 Body Composition (DEXA lean/fat) Morphology 0.0777327 -0.0119735 0.1674390 0.0457693 0.2020776 0.1083557 0.2957996 0.0478182 0.1235292 0.0638629 0.1831955 0.0304425
forelimb and hindlimb grip strength measurement mean 1 Grip Strength Morphology 0.0578158 0.0039998 0.1116318 0.0274577 0.1145986 0.0530521 0.1761451 0.0314018 0.0541888 0.0294838 0.0788938 0.0126048
forelimb grip strength measurement mean 1 Grip Strength Morphology 0.0265051 -0.0187240 0.0717341 0.0230765 0.0995076 0.0539740 0.1450413 0.0232319 0.0697061 0.0438625 0.0955496 0.0131857
fractional shortening 1 Echo Heart -0.0148852 -0.1161666 0.0863961 0.0516751 -0.0575326 -0.1558559 0.0407907 0.0501659 -0.0413498 -0.0567105 -0.0259891 0.0078372
free fatty acids 1 Clinical Chemistry Physiology 0.0281576 -0.1002531 0.1565683 0.0655169 0.0554109 -0.0736861 0.1845079 0.0658670 0.0193783 -0.0093700 0.0481266 0.0146678
fructosamine 1 Clinical Chemistry Physiology -0.0397864 -0.1198801 0.0403073 0.0408649 -0.0678231 -0.1513538 0.0157075 0.0426184 -0.0283579 -0.0692447 0.0125289 0.0208610
glucose 1 Clinical Chemistry Physiology 0.0692601 0.0184025 0.1201176 0.0259482 0.1279473 0.0423001 0.2135946 0.0436984 0.0650887 0.0218496 0.1083279 0.0220612
hdl-cholesterol 1 Clinical Chemistry Physiology -0.0650177 -0.1255786 -0.0044568 0.0308990 0.1724354 0.0701062 0.2747646 0.0522097 0.2606961 0.2180421 0.3033501 0.0217626
heart weight 1 Heart Weight Morphology 0.1766832 0.0672843 0.2860820 0.0558168 0.3651806 0.2169840 0.5133772 0.0756119 0.1737615 0.1409037 0.2066193 0.0167645
heart weight normalised against body weight 1 Heart Weight Morphology 0.0794303 -0.0060591 0.1649198 0.0436179 0.0355574 -0.0973272 0.1684419 0.0677995 -0.0495578 -0.0835809 -0.0155346 0.0173591
hematocrit 1 Hematology Hematology 0.0566356 -0.0516862 0.1649575 0.0552673 0.0737071 -0.0328632 0.1802774 0.0543736 0.0173967 0.0035179 0.0312754 0.0070811
hemoglobin 1 Hematology Hematology 0.0867000 0.0269936 0.1464064 0.0304630 0.0867345 0.0194022 0.1540668 0.0343538 0.0051992 -0.0080216 0.0184199 0.0067454
hr 1 Electrocardiogram (ECG) Heart -0.0634490 -0.1734699 0.0465718 0.0561341 -0.0140315 -0.1488474 0.1207843 0.0687849 0.0406617 -0.0139214 0.0952448 0.0278490
hrv 1 Electrocardiogram (ECG) Heart 0.1722593 0.1094294 0.2350892 0.0320567 -0.0813225 -0.2125462 0.0499011 0.0669521 -0.2504990 -0.3657436 -0.1352545 0.0587993
initial response to glucose challenge 1 Intraperitoneal glucose tolerance test (IPGTT) Metabolism -0.0968821 -0.1503780 -0.0433861 0.0272943 0.0429971 0.0141807 0.0718136 0.0147026 0.1183626 0.0853242 0.1514009 0.0168566
insulin 1 Insulin Blood Level Metabolism -0.0993292 -0.3721975 0.1735391 0.1392211 0.1774003 -0.1938091 0.5486096 0.1893960 0.4445455 0.0944498 0.7946412 0.1786236
iron 1 Clinical Chemistry Physiology -0.0974214 -0.2141737 0.0193310 0.0595686 -0.2534898 -0.3963648 -0.1106147 0.0728968 -0.1527977 -0.1930307 -0.1125646 0.0205274
lactate dehydrogenase 1 Clinical Chemistry Physiology 0.0941249 -0.0214022 0.2096519 0.0589435 0.1409270 -0.0620594 0.3439133 0.1035664 0.0318801 -0.1412218 0.2049819 0.0883189
latency to center entry 1 Open Field Behaviour 0.1254239 0.0330185 0.2178293 0.0471465 0.3641221 0.2056000 0.5226441 0.0808801 0.2734519 0.0739366 0.4729672 0.1017954
ldl-cholesterol 1 Clinical Chemistry Physiology 0.4231644 0.1551776 0.6911512 0.1367305 0.2669283 -0.0956833 0.6295400 0.1850093 -0.1615499 -0.6010478 0.2779480 0.2242378
lean mass 1 Body Composition (DEXA lean/fat) Morphology 0.1435756 0.0759342 0.2112170 0.0345115 0.3382447 0.2664863 0.4100031 0.0366121 0.1928945 0.1752425 0.2105465 0.0090063
lean/body weight 1 Body Composition (DEXA lean/fat) Morphology 0.1953833 0.0912480 0.2995186 0.0531312 0.1840786 0.0863764 0.2817807 0.0498490 -0.0122785 -0.0257504 0.0011934 0.0068736
left anterior chamber depth 1 Eye Morphology Eye -0.1854856 -0.4305058 0.0595347 0.1250126 -0.1534983 -0.4007283 0.0937316 0.1261401 0.0331746 0.0284172 0.0379321 0.0024273
left corneal thickness 1 Eye Morphology Eye -0.1446634 -0.2339950 -0.0553319 0.0455782 -0.1352252 -0.2234178 -0.0470327 0.0449970 0.0075283 -0.0057082 0.0207648 0.0067535
left inner nuclear layer 1 Eye Morphology Eye 0.0480458 -0.0360706 0.1321622 0.0429173 0.0487217 -0.0347622 0.1322057 0.0425946 0.0006956 -0.0095012 0.0108923 0.0052025
left outer nuclear layer 1 Eye Morphology Eye -0.0675012 -0.1511666 0.0161641 0.0426872 -0.0618025 -0.1452865 0.0216814 0.0425946 0.0063811 0.0011702 0.0115921 0.0026587
left posterior chamber depth 1 Eye Morphology Eye -0.2631046 -0.4734756 -0.0527336 0.1073341 -0.2687360 -0.4790035 -0.0584686 0.1072813 -0.0026027 -0.0146655 0.0094600 0.0061546
left total retinal thickness 1 Eye Morphology Eye -0.1975770 -0.4386627 0.0435087 0.1230052 -0.1932648 -0.4269751 0.0404456 0.1192422 0.0027995 -0.0034907 0.0090898 0.0032094
locomotor activity 1 Combined SHIRPA and Dysmorphology Behaviour 0.0960106 0.0224214 0.1695997 0.0375462 -0.0159064 -0.0579694 0.0261566 0.0214611 -0.1105803 -0.1761043 -0.0450562 0.0334313
lvawd 1 Echo Heart 0.0228924 -0.0247048 0.0704896 0.0242847 0.0454075 -0.0013249 0.0921399 0.0238435 0.0246614 0.0114095 0.0379132 0.0067613
lvaws 1 Echo Heart -0.0017749 -0.2517581 0.2482083 0.1275448 0.0232601 -0.1776617 0.2241819 0.1025130 0.0112569 -0.0306073 0.0531211 0.0213597
lvidd 1 Echo Heart 0.0453256 -0.0241892 0.1148405 0.0354674 0.0981450 0.0208146 0.1754754 0.0394550 0.0528053 0.0378669 0.0677436 0.0076218
lvids 1 Echo Heart -0.0635228 -0.1990947 0.0720491 0.0691706 0.0083352 -0.1335894 0.1502598 0.0724118 0.0756177 0.0525777 0.0986576 0.0117553
lvpwd 1 Echo Heart -0.0317376 -0.1258062 0.0623311 0.0479951 -0.0104248 -0.1271922 0.1063426 0.0595763 0.0302674 0.0131900 0.0473448 0.0087131
lvpws 1 Echo Heart -0.0190522 -0.1014670 0.0633627 0.0420492 0.0089592 -0.0823356 0.1002540 0.0465798 0.0268487 0.0063146 0.0473828 0.0104768
magnesium 1 Urinalysis Physiology 0.0161699 -0.0231196 0.0554593 0.0200460 -0.0513056 -0.1167021 0.0140909 0.0333662 -0.0413354 -0.1135580 0.0308871 0.0368489
mean cell hemoglobin concentration 1 Hematology Hematology 0.0378015 -0.0880637 0.1636666 0.0642181 0.0253063 -0.1086076 0.1592202 0.0683247 -0.0113450 -0.0150702 -0.0076199 0.0019006
mean cell volume 1 Hematology Hematology 0.0039175 -0.0957495 0.1035845 0.0508514 -0.0030447 -0.0961742 0.0900848 0.0475159 -0.0063502 -0.0099649 -0.0027355 0.0018443
mean corpuscular hemoglobin 1 Hematology Hematology -0.0025833 -0.0653065 0.0601398 0.0320022 -0.0193465 -0.0824670 0.0437741 0.0322049 -0.0169768 -0.0197231 -0.0142305 0.0014012
mean platelet volume 1 Hematology Hematology 0.0487366 -0.0044688 0.1019419 0.0271461 0.0353913 -0.0210323 0.0918150 0.0287881 -0.0174066 -0.0276044 -0.0072089 0.0052030
mean r amplitude 1 Electrocardiogram (ECG) Heart 0.0084703 -0.0282092 0.0451499 0.0187144 -0.0948208 -0.1630495 -0.0265922 0.0348112 -0.0835612 -0.1503108 -0.0168116 0.0340565
mean sr amplitude 1 Electrocardiogram (ECG) Heart 0.0284617 -0.0131943 0.0701178 0.0212535 -0.0876811 -0.1270777 -0.0482845 0.0201007 -0.1130259 -0.1558048 -0.0702470 0.0218264
number of center entries 1 Open Field Behaviour 0.0150703 -0.0534907 0.0836313 0.0349807 -0.0361259 -0.0952472 0.0229955 0.0301645 -0.0588092 -0.1679907 0.0503723 0.0557059
number of rears - total 1 Open Field Behaviour -0.0011326 -0.1141113 0.1118461 0.0576432 0.1869490 -0.0392422 0.4131402 0.1154058 0.1794328 0.0568682 0.3019974 0.0625341
others 1 Immunophenotyping Immunology -0.1684902 -0.2596648 -0.0773156 0.0465185 -0.1515195 -0.2435956 -0.0594434 0.0469785 0.0196158 0.0049349 0.0342967 0.0074904
pdcs 1 Immunophenotyping Immunology -0.1732553 -0.4003845 0.0538738 0.1158844 -0.2572491 -0.7186201 0.2041219 0.2353977 -0.0915619 -0.2522236 0.0690997 0.0819717
percentage center time 1 Open Field Behaviour -0.0219679 -0.0863184 0.0423826 0.0328325 -0.0188907 -0.0912088 0.0534274 0.0368977 -0.0061802 -0.0972542 0.0848938 0.0464672
periphery average speed 1 Open Field Behaviour -0.0444272 -0.1082870 0.0194327 0.0325822 -0.1401304 -0.2117709 -0.0684898 0.0365520 -0.0963838 -0.1446043 -0.0481633 0.0246028
periphery distance travelled 1 Open Field Behaviour -0.0313217 -0.0918314 0.0291879 0.0308728 -0.1342236 -0.1874097 -0.0810376 0.0271362 -0.1037239 -0.1714836 -0.0359643 0.0345719
periphery permanence time 1 Open Field Behaviour -0.0369177 -0.1277076 0.0538721 0.0463222 -0.0294978 -0.1006346 0.0416390 0.0362950 0.0077038 -0.0137850 0.0291927 0.0109639
periphery resting time 1 Open Field Behaviour -0.0536346 -0.1266045 0.0193353 0.0372302 -0.0572459 -0.1071515 -0.0073404 0.0254625 0.0026007 -0.0558538 0.0610552 0.0298243
phosphorus 1 Clinical Chemistry Physiology -0.0485897 -0.0839101 -0.0132693 0.0180209 -0.0826120 -0.1576473 -0.0075767 0.0382840 -0.0420616 -0.0813582 -0.0027650 0.0200497
platelet count 1 Hematology Hematology 0.0737198 0.0205862 0.1268534 0.0271095 0.2415135 0.1865330 0.2964940 0.0280518 0.1642192 0.1369820 0.1914563 0.0138968
pnn5(6>ms) 1 Electrocardiogram (ECG) Heart 0.2906905 0.1716202 0.4097607 0.0607512 -0.2926013 -0.5272121 -0.0579905 0.1197016 -0.6004767 -0.9244113 -0.2765420 0.1652758
potassium 1 Clinical Chemistry Physiology -0.0705522 -0.2214989 0.0803945 0.0770150 -0.0074675 -0.1729366 0.1580015 0.0844245 0.0704162 0.0476647 0.0931676 0.0116081
pq 1 Electrocardiogram (ECG) Heart -0.0650960 -0.1538776 0.0236857 0.0452976 -0.0648322 -0.1270688 -0.0025955 0.0317540 0.0015656 -0.0259865 0.0291178 0.0140575
pr 1 Electrocardiogram (ECG) Heart -0.0564860 -0.1048371 -0.0081349 0.0246694 -0.0754718 -0.1235224 -0.0274213 0.0245160 -0.0183785 -0.0319887 -0.0047684 0.0069441
qrs 1 Electrocardiogram (ECG) Heart 0.0725454 0.0354722 0.1096185 0.0189152 0.0681074 0.0300869 0.1061278 0.0193986 -0.0054233 -0.0154885 0.0046418 0.0051354
qtc 1 Electrocardiogram (ECG) Heart 0.0328106 -0.0101032 0.0757244 0.0218952 0.0310473 -0.0207365 0.0828310 0.0264208 -0.0005046 -0.0085696 0.0075604 0.0041149
qtc dispersion 1 Electrocardiogram (ECG) Heart 0.0031258 -0.0523919 0.0586435 0.0283259 -0.0046501 -0.1060530 0.0967528 0.0517371 -0.0077373 -0.0510162 0.0355416 0.0220815
red blood cell count 1 Hematology Hematology 0.0773455 0.0071933 0.1474977 0.0357926 0.0997278 0.0316996 0.1677560 0.0347089 0.0228493 0.0088583 0.0368404 0.0071384
red blood cell distribution width 1 Hematology Hematology 0.1248464 -0.0035148 0.2532076 0.0654916 0.1353460 -0.0035862 0.2742782 0.0708851 0.0104789 -0.0032056 0.0241635 0.0069821
respiration rate 1 Echo Heart -0.1384843 -0.2178736 -0.0590950 0.0405055 -0.0703570 -0.1795875 0.0388735 0.0557309 0.0611034 0.0227141 0.0994926 0.0195867
respiratory exchange ratio 1 Indirect Calorimetry Metabolism -0.0116565 -0.0896490 0.0663361 0.0397928 -0.0106530 -0.0878483 0.0665424 0.0393861 0.0017027 -0.0057348 0.0091402 0.0037947
right anterior chamber depth 1 Eye Morphology Eye -0.4491432 -1.3293546 0.4310682 0.4490957 -0.4157377 -1.2918620 0.4603867 0.4470104 0.0316098 0.0264512 0.0367685 0.0026320
right corneal thickness 1 Eye Morphology Eye -0.0355898 -0.2280522 0.1568726 0.0981969 -0.0306550 -0.1963692 0.1350592 0.0845496 -0.0013855 -0.0237830 0.0210121 0.0114275
right inner nuclear layer 1 Eye Morphology Eye -0.2545083 -0.7633116 0.2542949 0.2595983 -0.2785114 -0.8373133 0.2802906 0.2851083 -0.0175090 -0.0664158 0.0313978 0.0249529
right outer nuclear layer 1 Eye Morphology Eye 0.0061253 -0.0781241 0.0903746 0.0429851 0.0109098 -0.0731427 0.0949622 0.0428847 0.0055513 0.0000519 0.0110508 0.0028059
right posterior chamber depth 1 Eye Morphology Eye -0.0775673 -0.2905688 0.1354341 0.1086762 -0.0764571 -0.2893152 0.1364010 0.1086031 0.0071990 -0.0178434 0.0322413 0.0127769
right total retinal thickness 1 Eye Morphology Eye -0.1987993 -0.6457320 0.2481333 0.2280310 -0.1925482 -0.6285715 0.2434750 0.2224649 0.0052882 -0.0045957 0.0151720 0.0050429
rmssd 1 Electrocardiogram (ECG) Heart 0.1800273 -0.0882317 0.4482864 0.1368694 -0.0161048 -0.4112809 0.3790712 0.2016241 -0.1178703 -0.2449843 0.0092436 0.0648552
rp macrophage (cd19- cd11c-) 1 Immunophenotyping Immunology -0.0765771 -0.3398075 0.1866533 0.1343037 -0.0747691 -0.3351316 0.1855933 0.1328404 -0.0746396 -0.2072980 0.0580188 0.0676841
rr 1 Electrocardiogram (ECG) Heart -0.0761505 -0.1876687 0.0353678 0.0568981 -0.0896869 -0.2063458 0.0269721 0.0595210 -0.0125023 -0.0214082 -0.0035963 0.0045440
sodium 1 Clinical Chemistry Physiology 0.0262100 -0.1171674 0.1695873 0.0731531 0.0338228 -0.1337162 0.2013618 0.0854806 0.0099680 0.0065815 0.0133545 0.0017278
spleen weight 1 Immunophenotyping Immunology 0.1874259 -0.0500875 0.4249393 0.1211825 0.1133706 -0.1604807 0.3872220 0.1397227 -0.1542349 -0.2104415 -0.0980283 0.0286774
st 1 Electrocardiogram (ECG) Heart 0.0032888 -0.0544512 0.0610288 0.0294597 -0.0054976 -0.0811810 0.0701858 0.0386147 -0.0034902 -0.0175917 0.0106113 0.0071948
stroke volume 1 Echo Heart 0.0594276 -0.0782445 0.1970997 0.0702422 0.1574330 0.0091891 0.3056769 0.0756360 0.0937375 0.0775587 0.1099162 0.0082546
tibia length 1 Heart Weight Morphology -0.1475403 -0.4396127 0.1445320 0.1490192 -0.1374401 -0.4261352 0.1512551 0.1472961 0.0095199 0.0059199 0.0131200 0.0018368
total bilirubin 1 Clinical Chemistry Physiology 0.0605449 -0.0097669 0.1308567 0.0358740 0.0022671 -0.0859910 0.0905252 0.0450305 -0.0550333 -0.0979518 -0.0121148 0.0218976
total cholesterol 1 Clinical Chemistry Physiology 0.0942595 -0.0751596 0.2636786 0.0864399 0.3142208 0.1125613 0.5158803 0.1028894 0.2027583 0.1750477 0.2304688 0.0141383
total food intake 1 Indirect Calorimetry Metabolism -0.1192293 -0.2542902 0.0158316 0.0689099 -0.0964842 -0.2564912 0.0635228 0.0816377 0.0267691 -0.0233285 0.0768667 0.0255605
total protein 1 Clinical Chemistry Physiology -0.0422347 -0.0623878 -0.0220816 0.0102824 -0.0355909 -0.0619127 -0.0092692 0.0134297 0.0092660 -0.0008158 0.0193478 0.0051439
total water intake 1 Indirect Calorimetry Metabolism -0.1457383 -0.2373165 -0.0541601 0.0467244 -0.2097443 -0.2681948 -0.1512937 0.0298223 -0.0654284 -0.1374220 0.0065653 0.0367321
triglycerides 1 Clinical Chemistry Physiology -0.0320020 -0.1233659 0.0593619 0.0466151 0.3268957 0.2087111 0.4450803 0.0602994 0.3473552 0.2592006 0.4355098 0.0449777
urea (blood urea nitrogen - bun) 1 Clinical Chemistry Physiology -0.1405306 -0.2664120 -0.0146491 0.0642264 -0.0950040 -0.2507897 0.0607817 0.0794840 0.0403162 0.0051883 0.0754441 0.0179227
uric acid 1 Clinical Chemistry Physiology 0.0367062 -0.0660619 0.1394744 0.0524337 0.3626957 0.0914512 0.6339402 0.1383926 0.4472349 -0.0801891 0.9746588 0.2690988
white blood cell count 1 Hematology Hematology -0.0907957 -0.1703063 -0.0112852 0.0405673 0.1168446 -0.0023934 0.2360826 0.0608368 0.1978876 0.1368305 0.2589447 0.0311521
whole arena average speed 1 Open Field Behaviour -0.0156634 -0.0857564 0.0544296 0.0357624 -0.1140149 -0.1840029 -0.0440269 0.0357088 -0.0997437 -0.1519566 -0.0475307 0.0266397
whole arena resting time 1 Open Field Behaviour -0.0531307 -0.1011672 -0.0050941 0.0245089 -0.0593672 -0.1076067 -0.0111276 0.0246125 0.0045878 -0.0513396 0.0605152 0.0285349


# trait_meta_results <- write.csv(metacombo, file = "export/trait_meta_results.csv")

3. Second-order meta analysis for functional groups

(Section H in Figure 3 in main article)

Performing meta-analyses (3 for each of the 9 grouping terms: lnCVR, lnVR, lnRR)

Preparation of data

Nesting, calculating the number of parameters within each grouping term, and running the meta-analysis

metacombo_final <- metacombo %>%
  group_by(GroupingTerm) %>%
   nest_legacy()   # we're using 'nest_legacy' to keep old syntax/functionality

# **calculate number of parameters per grouping term

metacombo_final <- metacombo_final %>% mutate(para_per_GroupingTerm = map_dbl(data, nrow))

# For all grouping terms
metacombo_final_all <- metacombo %>%
  nest_legacy() #'nest_legacy' to keep old syntax/functionality

# **Final fixed effects meta-analyses within grouping terms, with SE of the estimate

overall1 <- metacombo_final %>%

  mutate(
    model_lnCVR = map(data, ~ metafor::rma.uni(
      yi = .x$lnCVR, sei = (.x$lnCVR_upper - .x$lnCVR_lower) / (2 * 1.96),
      control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
    )),
    model_lnVR = map(data, ~ metafor::rma.uni(
      yi = .x$lnVR, sei = (.x$lnVR_upper - .x$lnVR_lower) / (2 * 1.96),
      control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
    )),
    model_lnRR = map(data, ~ metafor::rma.uni(
      yi = .x$lnRR, sei = (.x$lnRR_upper - .x$lnRR_lower) / (2 * 1.96),
      control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
    ))
  )

# **Final fixed effects meta-analyses ACROSS grouping terms, with SE of the estimate

overall_all1 <- metacombo_final_all %>%

  mutate(
    model_lnCVR = map(data, ~ metafor::rma.uni(
      yi = .x$lnCVR, sei = (.x$lnCVR_upper - .x$lnCVR_lower) / (2 * 1.96),
      control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
    )),
    model_lnVR = map(data, ~ metafor::rma.uni(
      yi = .x$lnVR, sei = (.x$lnVR_upper - .x$lnVR_lower) / (2 * 1.96),
      control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
    )),
    model_lnRR = map(data, ~ metafor::rma.uni(
      yi = .x$lnRR, sei = (.x$lnRR_upper - .x$lnRR_lower) / (2 * 1.96),
      control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
    ))
  )

Re-structuring the data for each grouping term

We here delete unused variables, and select the respective effect sizes. Please note - the referencing of the cells does NOT depend on previous ordering of the data. This would only be affected if the output structure from metafor::rma.uni changes.

Behaviour <- as.data.frame(overall1 %>% filter(., GroupingTerm == "Behaviour") %>% mutate(
  lnCVR = .[[4]][[1]]$b, lnCVR_lower = .[[4]][[1]]$ci.lb, lnCVR_upper = .[[4]][[1]]$ci.ub, lnCVR_se = .[[4]][[1]]$se,
  lnVR = .[[5]][[1]]$b, lnVR_lower = .[[5]][[1]]$ci.lb, lnVR_upper = .[[5]][[1]]$ci.ub, lnVR_se = .[[5]][[1]]$se,
  lnRR = .[[6]][[1]]$b, lnRR_lower = .[[6]][[1]]$ci.lb, lnRR_upper = .[[6]][[1]]$ci.ub, lnRR_se = .[[6]][[1]]$se
))[, c(1, 7:18)]

Immunology <- as.data.frame(overall1 %>% filter(., GroupingTerm == "Immunology") %>% mutate(
  lnCVR = .[[4]][[1]]$b, lnCVR_lower = .[[4]][[1]]$ci.lb, lnCVR_upper = .[[4]][[1]]$ci.ub, lnCVR_se = .[[4]][[1]]$se,
  lnVR = .[[5]][[1]]$b, lnVR_lower = .[[5]][[1]]$ci.lb, lnVR_upper = .[[5]][[1]]$ci.ub, lnVR_se = .[[5]][[1]]$se,
  lnRR = .[[6]][[1]]$b, lnRR_lower = .[[6]][[1]]$ci.lb, lnRR_upper = .[[6]][[1]]$ci.ub, lnRR_se = .[[6]][[1]]$se
))[, c(1, 7:18)]

Hematology <- as.data.frame(overall1 %>% filter(., GroupingTerm == "Hematology") %>% mutate(
  lnCVR = .[[4]][[1]]$b, lnCVR_lower = .[[4]][[1]]$ci.lb, lnCVR_upper = .[[4]][[1]]$ci.ub, lnCVR_se = .[[4]][[1]]$se,
  lnVR = .[[5]][[1]]$b, lnVR_lower = .[[5]][[1]]$ci.lb, lnVR_upper = .[[5]][[1]]$ci.ub, lnVR_se = .[[5]][[1]]$se,
  lnRR = .[[6]][[1]]$b, lnRR_lower = .[[6]][[1]]$ci.lb, lnRR_upper = .[[6]][[1]]$ci.ub, lnRR_se = .[[6]][[1]]$se
))[, c(1, 7:18)]

Hearing <- as.data.frame(overall1 %>% filter(., GroupingTerm == "Hearing") %>% mutate(
  lnCVR = .[[4]][[1]]$b, lnCVR_lower = .[[4]][[1]]$ci.lb, lnCVR_upper = .[[4]][[1]]$ci.ub, lnCVR_se = .[[4]][[1]]$se,
  lnVR = .[[5]][[1]]$b, lnVR_lower = .[[5]][[1]]$ci.lb, lnVR_upper = .[[5]][[1]]$ci.ub, lnVR_se = .[[5]][[1]]$se,
  lnRR = .[[6]][[1]]$b, lnRR_lower = .[[6]][[1]]$ci.lb, lnRR_upper = .[[6]][[1]]$ci.ub, lnRR_se = .[[6]][[1]]$se
))[, c(1, 7:18)]

Physiology <- as.data.frame(overall1 %>% filter(., GroupingTerm == "Physiology") %>% mutate(
  lnCVR = .[[4]][[1]]$b, lnCVR_lower = .[[4]][[1]]$ci.lb, lnCVR_upper = .[[4]][[1]]$ci.ub, lnCVR_se = .[[4]][[1]]$se,
  lnVR = .[[5]][[1]]$b, lnVR_lower = .[[5]][[1]]$ci.lb, lnVR_upper = .[[5]][[1]]$ci.ub, lnVR_se = .[[5]][[1]]$se,
  lnRR = .[[6]][[1]]$b, lnRR_lower = .[[6]][[1]]$ci.lb, lnRR_upper = .[[6]][[1]]$ci.ub, lnRR_se = .[[6]][[1]]$se
))[, c(1, 7:18)]

Metabolism <- as.data.frame(overall1 %>% filter(., GroupingTerm == "Metabolism") %>% mutate(
  lnCVR = .[[4]][[1]]$b, lnCVR_lower = .[[4]][[1]]$ci.lb, lnCVR_upper = .[[4]][[1]]$ci.ub, lnCVR_se = .[[4]][[1]]$se,
  lnVR = .[[5]][[1]]$b, lnVR_lower = .[[5]][[1]]$ci.lb, lnVR_upper = .[[5]][[1]]$ci.ub, lnVR_se = .[[5]][[1]]$se,
  lnRR = .[[6]][[1]]$b, lnRR_lower = .[[6]][[1]]$ci.lb, lnRR_upper = .[[6]][[1]]$ci.ub, lnRR_se = .[[6]][[1]]$se
))[, c(1, 7:18)]

Morphology <- as.data.frame(overall1 %>% filter(., GroupingTerm == "Morphology") %>% mutate(
  lnCVR = .[[4]][[1]]$b, lnCVR_lower = .[[4]][[1]]$ci.lb, lnCVR_upper = .[[4]][[1]]$ci.ub, lnCVR_se = .[[4]][[1]]$se,
  lnVR = .[[5]][[1]]$b, lnVR_lower = .[[5]][[1]]$ci.lb, lnVR_upper = .[[5]][[1]]$ci.ub, lnVR_se = .[[5]][[1]]$se,
  lnRR = .[[6]][[1]]$b, lnRR_lower = .[[6]][[1]]$ci.lb, lnRR_upper = .[[6]][[1]]$ci.ub, lnRR_se = .[[6]][[1]]$se
))[, c(1, 7:18)]

Heart <- as.data.frame(overall1 %>% filter(., GroupingTerm == "Heart") %>% mutate(
  lnCVR = .[[4]][[1]]$b, lnCVR_lower = .[[4]][[1]]$ci.lb, lnCVR_upper = .[[4]][[1]]$ci.ub, lnCVR_se = .[[4]][[1]]$se,
  lnVR = .[[5]][[1]]$b, lnVR_lower = .[[5]][[1]]$ci.lb, lnVR_upper = .[[5]][[1]]$ci.ub, lnVR_se = .[[5]][[1]]$se,
  lnRR = .[[6]][[1]]$b, lnRR_lower = .[[6]][[1]]$ci.lb, lnRR_upper = .[[6]][[1]]$ci.ub, lnRR_se = .[[6]][[1]]$se
))[, c(1, 7:18)]

Eye <- as.data.frame(overall1 %>% filter(., GroupingTerm == "Eye") %>% mutate(
  lnCVR = .[[4]][[1]]$b, lnCVR_lower = .[[4]][[1]]$ci.lb, lnCVR_upper = .[[4]][[1]]$ci.ub, lnCVR_se = .[[4]][[1]]$se,
  lnVR = .[[5]][[1]]$b, lnVR_lower = .[[5]][[1]]$ci.lb, lnVR_upper = .[[5]][[1]]$ci.ub, lnVR_se = .[[5]][[1]]$se,
  lnRR = .[[6]][[1]]$b, lnRR_lower = .[[6]][[1]]$ci.lb, lnRR_upper = .[[6]][[1]]$ci.ub, lnRR_se = .[[6]][[1]]$se
))[, c(1, 7:18)]

All <- as.data.frame(overall_all1 %>% mutate(
  lnCVR = .[[2]][[1]]$b, lnCVR_lower = .[[2]][[1]]$ci.lb, lnCVR_upper = .[[2]][[1]]$ci.ub, lnCVR_se = .[[2]][[1]]$se, lnVR = .[[3]][[1]]$b, lnVR_lower = .[[3]][[1]]$ci.lb, lnVR_upper = .[[3]][[1]]$ci.ub, lnVR_se = .[[3]][[1]]$se,
  lnRR = .[[4]][[1]]$b, lnRR_lower = .[[4]][[1]]$ci.lb, lnRR_upper = .[[4]][[1]]$ci.ub, lnRR_se = .[[4]][[1]]$se
))[, c(5:16)]

All$lnCVR <- as.numeric(All$lnCVR)
All$lnVR <- as.numeric(All$lnVR)
All$lnRR <- as.numeric(All$lnRR)
All <- All %>% mutate(GroupingTerm = "All")

overall2 <- bind_rows(Behaviour, Morphology, Metabolism, Physiology, Immunology, Hematology, Heart, Hearing, Eye, All) #FZ: warnings are ok

Visualisation

Figure 4

Preparation for plots: Count data, based on First-order meta analysis results

This includes all separate eligible traits. Re-ordering of grouping terms


meta_clean$GroupingTerm <- factor(meta_clean$GroupingTerm, levels = c("Behaviour", "Morphology", "Metabolism", "Physiology", "Immunology", "Hematology", "Heart", "Hearing", "Eye"))
meta_clean$GroupingTerm <- factor(meta_clean$GroupingTerm, rev(levels(meta_clean$GroupingTerm)))

# *Preparing data for all traits

meta.plot2.all <- meta_clean %>%
  select(lnCVR, lnVR, lnRR, GroupingTerm) %>%
  arrange(GroupingTerm)

meta.plot2.all.b <- gather(meta.plot2.all, trait, value, c(lnCVR, lnRR)) # lnVR has been removed here and in the steps below, as this is only included in the supplemental figure

meta.plot2.all.b$trait <- factor(meta.plot2.all.b$trait, levels = c("lnCVR", "lnRR")) 
meta.plot2.all.c <- meta.plot2.all.b %>%
  group_by_at(vars(trait, GroupingTerm)) %>%
  summarise(
    malebias = sum(value > 0), femalebias = sum(value <= 0), total = malebias + femalebias,
    malepercent = malebias * 100 / total, femalepercent = femalebias * 100 / total
  )

meta.plot2.all.c$label <- "All traits"

# restructure to create stacked bar plots

meta.plot2.all.d <- as.data.frame(meta.plot2.all.c)
meta.plot2.all.e <- gather(meta.plot2.all.d, key = sex, value = percent, malepercent:femalepercent, factor_key = TRUE)

# create new sample size variable

meta.plot2.all.e$samplesize <- with(meta.plot2.all.e, ifelse(sex == "malepercent", malebias, femalebias))

# add summary row ('All') and re-arrange rows into correct order for plotting #FZ added

meta.plot2.all.f <- meta.plot2.all.e %>% group_by(trait, sex) %>% 
    summarise(GroupingTerm = "All", malebias = sum(malebias), femalebias = sum(femalebias), total = malebias + femalebias, 
    label = "All traits", samplesize = sum(samplesize)) %>%
    mutate(percent = ifelse(sex == "femalepercent", femalebias*100/(malebias+femalebias), malebias*100/(malebias+femalebias))) %>%
    bind_rows(meta.plot2.all.e, .) %>%
    mutate(rownumber = row_number()) %>%
    .[c(37, 1:9, 39, 10:18, 38, 19:27, 40, 28:36), ]
binding factor and character vector, coercing into character vectorbinding character and factor vector, coercing into character vector
meta.plot2.all.f$GroupingTerm <- factor(meta.plot2.all.f$GroupingTerm, levels = c("Behaviour", "Morphology", "Metabolism", "Physiology", "Immunology", "Hematology", "Heart", "Hearing", "Eye", "All")) 
meta.plot2.all.f$GroupingTerm <- factor(meta.plot2.all.f$GroupingTerm, rev(levels(meta.plot2.all.f$GroupingTerm)))

malebias_Fig2_alltraits <-
  ggplot(meta.plot2.all.f) +
  aes(x = GroupingTerm, y = percent, fill = sex) +
  geom_col() +
  geom_hline(yintercept = 50, linetype = "dashed", color = "gray40") +
  geom_text(
    data = subset(meta.plot2.all.f, samplesize != 0), aes(label = samplesize), position = position_stack(vjust = .5),
    color = "white", size = 3.5
  ) +
  facet_grid(
    cols = vars(trait), rows = vars(label), labeller = label_wrap_gen(width = 18),
    scales = "free", space = "free"
  ) +
  scale_fill_brewer(palette = "Set2") +
  theme_bw(base_size = 18) +
  theme(
    strip.text.y = element_text(angle = 270, size = 10, margin = margin(t = 15, r = 15, b = 15, l = 15)),
    strip.text.x = element_text(size = 12),
    strip.background = element_rect(colour = NULL, linetype = "blank", fill = "gray90"),
    text = element_text(size = 14),
    panel.spacing = unit(0.5, "lines"),
    panel.border = element_blank(),
    axis.line = element_line(),
    panel.grid.major.x = element_line(linetype = "solid", colour = "gray95"),
    panel.grid.major.y = element_line(linetype = "solid", color = "gray95"),
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank(),
    legend.position = "none",
    axis.title.x = element_blank(),
    axis.title.y = element_blank()
  ) +
  coord_flip()

# malebias_Fig2_alltraits     #(panel A in Figure 4 in ms)

Overall results of second order meta analysis (Figure 4, Panel B)

Restructure data for plotting

Data are restructured, and grouping terms are being re-ordered

overall3 <- gather(overall2, parameter, value, c(lnCVR, lnRR), factor_key = TRUE) # lnVR,

lnCVR.ci <- overall3 %>%
  filter(parameter == "lnCVR") %>%
  mutate(ci.low = lnCVR_lower, ci.high = lnCVR_upper)
lnVR.ci <- overall3 %>%
  filter(parameter == "lnVR") %>%
  mutate(ci.low = lnVR_lower, ci.high = lnVR_upper)
lnRR.ci <- overall3 %>%
  filter(parameter == "lnRR") %>%
  mutate(ci.low = lnRR_lower, ci.high = lnRR_upper)

overall4 <- bind_rows(lnCVR.ci, lnRR.ci) %>% select(GroupingTerm, parameter, value, ci.low, ci.high) # lnVR.ci,

# re-order Grouping Terms

overall4$GroupingTerm <- factor(overall4$GroupingTerm, levels = c("Behaviour", "Morphology", "Metabolism", "Physiology", "Immunology", "Hematology", "Heart", "Hearing", "Eye", "All"))
overall4$GroupingTerm <- factor(overall4$GroupingTerm, rev(levels(overall4$GroupingTerm)))
overall4$label <- "All traits"

kable(cbind(overall4, overall4)) %>%
  kable_styling() %>%
  scroll_box(width = "100%", height = "200px")
GroupingTerm parameter value ci.low ci.high label GroupingTerm parameter value ci.low ci.high label
Behaviour lnCVR -0.0035049 -0.0240688 0.0170591 All traits Behaviour lnCVR -0.0035049 -0.0240688 0.0170591 All traits
Morphology lnCVR 0.0774453 0.0414171 0.1134734 All traits Morphology lnCVR 0.0774453 0.0414171 0.1134734 All traits
Metabolism lnCVR -0.0430831 -0.1125945 0.0264283 All traits Metabolism lnCVR -0.0430831 -0.1125945 0.0264283 All traits
Physiology lnCVR 0.0126792 -0.0140094 0.0393678 All traits Physiology lnCVR 0.0126792 -0.0140094 0.0393678 All traits
Immunology lnCVR -0.0681817 -0.0980135 -0.0383499 All traits Immunology lnCVR -0.0681817 -0.0980135 -0.0383499 All traits
Hematology lnCVR 0.0217865 -0.0165045 0.0600776 All traits Hematology lnCVR 0.0217865 -0.0165045 0.0600776 All traits
Heart lnCVR 0.0183839 -0.0128375 0.0496053 All traits Heart lnCVR 0.0183839 -0.0128375 0.0496053 All traits
Hearing lnCVR 0.0157302 -0.0111999 0.0426603 All traits Hearing lnCVR 0.0157302 -0.0111999 0.0426603 All traits
Eye lnCVR -0.0817932 -0.1476821 -0.0159043 All traits Eye lnCVR -0.0817932 -0.1476821 -0.0159043 All traits
All lnCVR 0.0046553 -0.0086242 0.0179348 All traits All lnCVR 0.0046553 -0.0086242 0.0179348 All traits
Behaviour lnRR -0.0199206 -0.0634388 0.0235976 All traits Behaviour lnRR -0.0199206 -0.0634388 0.0235976 All traits
Morphology lnRR 0.0678160 0.0072225 0.1284095 All traits Morphology lnRR 0.0678160 0.0072225 0.1284095 All traits
Metabolism lnRR 0.1422577 0.0364352 0.2480801 All traits Metabolism lnRR 0.1422577 0.0364352 0.2480801 All traits
Physiology lnRR 0.0163695 -0.0443364 0.0770753 All traits Physiology lnRR 0.0163695 -0.0443364 0.0770753 All traits
Immunology lnRR -0.0574840 -0.1074213 -0.0075466 All traits Immunology lnRR -0.0574840 -0.1074213 -0.0075466 All traits
Hematology lnRR 0.0388537 -0.0024274 0.0801348 All traits Hematology lnRR 0.0388537 -0.0024274 0.0801348 All traits
Heart lnRR -0.0048933 -0.0324240 0.0226374 All traits Heart lnRR -0.0048933 -0.0324240 0.0226374 All traits
Hearing lnRR -0.0132366 -0.0335982 0.0071251 All traits Hearing lnRR -0.0132366 -0.0335982 0.0071251 All traits
Eye lnRR 0.0091186 0.0012071 0.0170302 All traits Eye lnRR 0.0091186 0.0012071 0.0170302 All traits
All lnRR 0.0124332 -0.0061474 0.0310138 All traits All lnRR 0.0124332 -0.0061474 0.0310138 All traits
Metameta_Fig3_alltraits <- overall4 %>%

  ggplot(aes(y = GroupingTerm, x = value)) +
  geom_errorbarh(aes(
    xmin = ci.low,
    xmax = ci.high
  ),
  height = 0.1, show.legend = FALSE
  ) +
  geom_point(aes(shape = parameter),
    fill = "black",
    color = "black", size = 2.2,
    show.legend = FALSE
  ) +
  scale_x_continuous(
    limits = c(-0.24, 0.25),
    breaks = c(-0.2, -0.1, 0, 0.1, 0.2),
    name = "Effect size"
  ) +
  geom_vline(
    xintercept = 0,
    color = "black",
    linetype = "dashed"
  ) +
  facet_grid(
    cols = vars(parameter), rows = vars(label),
    labeller = label_wrap_gen(width = 23),
    scales = "free",
    space = "free"
  ) +
  theme_bw() +
  theme(
    strip.text.y = element_text(angle = 270, size = 10, margin = margin(t = 15, r = 15, b = 15, l = 15)),
    strip.text.x = element_text(size = 12),
    strip.background = element_rect(colour = NULL, linetype = "blank", fill = "gray90"),
    text = element_text(size = 14),
    panel.spacing = unit(0.5, "lines"),
    panel.border = element_blank(),
    axis.line = element_line(),
    panel.grid.major.x = element_line(linetype = "solid", colour = "gray95"),
    panel.grid.major.y = element_line(linetype = "solid", color = "gray95"),
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank(),
    legend.title = element_blank(),
    axis.title.x = element_text(hjust = 0.5, size = 14),
    axis.title.y = element_blank()
  )

# Metameta_Fig3_alltraits

Fig 4

Join the different parts and #TO DO!! add M / F symbols in Metameta_Fig3_alltraits

#Test
#male <- readPNG(system.file("img", "male"))
#test <- Metameta_Fig3_alltraits 

#library(png)
Fig4 <- ggarrange(malebias_Fig2_alltraits, Metameta_Fig3_alltraits,  nrow = 2, align = "v", heights = c(1, 1), labels = c("A", "B"))
Fig4

Figure 4:

Panel A shows the numbers of traits across functional groups that are either male-biased (blue-green) or female-biased (orange-red), as calculated in Step D (figure 3). Panel B shows effect sizes and 95% CI from separate meta-analysis for each functional group (step H in Figure 3). Both panels represent results evaluated across all traits (Phase 3, Figure 3). Traits that are male biased are Male data is shown in blue, whereas female bias data is represented in orange.

Figure 5

Preparing data for traits with CI not overlapping 0

To further investigate sex bias in this dataset, and in particular if the extent of sex bias differs between traits, we investigate the magnitude of male- and female bias in significantly different traits on (both for means and variability)

To do this, we select only traits that have CIs that do not overlap with zero. ### FELIX: “ALL” missing. This figure is panel A in Fig 5


meta.plot2.sig <- meta_clean %>%
  mutate(
    lnCVRsig = ifelse(lnCVR_lower * lnCVR_upper > 0, 1, 0), lnVRsig = ifelse(lnVR_lower * lnVR_upper > 0, 1, 0),
    lnRRsig = ifelse(lnRR_lower * lnRR_upper > 0, 1, 0)
  )

meta.plot2.sig.b <- meta.plot2.sig[, c("lnCVR", "lnRR", "lnCVRsig", "lnVRsig", "lnRRsig", "GroupingTerm")] # "lnVR",

meta.plot2.sig.c <- gather(meta.plot2.sig.b, trait, value, lnCVR:lnRR)
meta.plot2.sig.c$sig <- "placeholder"

meta.plot2.sig.c$trait <- factor(meta.plot2.sig.c$trait, levels = c("lnCVR", "lnRR")) # "lnVR",

meta.plot2.sig.c$sig <- ifelse(meta.plot2.sig.c$trait == "lnCVR", meta.plot2.sig.c$lnCVRsig,
  ifelse(meta.plot2.sig.c$trait == "lnVR", meta.plot2.sig.c$lnVRsig, meta.plot2.sig.c$lnRRsig)
)

# choosing sex biased ln-ratios significantly larger than 0
meta.plot2.sig.malebias <- meta.plot2.sig.c %>%
  group_by_at(vars(trait, GroupingTerm)) %>%
  filter(sig == 1) %>%
  summarise(male_sig = sum(value > 0), female_sig = sum(value < 0), total = male_sig + female_sig)

meta.plot2.sig.malebias <- ungroup(meta.plot2.sig.malebias) %>%
  add_row(trait = "lnCVR", GroupingTerm = "Hearing", male_sig = 0, female_sig = 0, .before = 4) %>% # add "Hearing" for lnCVR (not filtered as only zeros)
  mutate(malepercent = male_sig * 100 / total, femalepercent = female_sig * 100 / total)

meta.plot2.sig.malebias$label <- "CI not overlapping zero"

# restructure to create stacked bar plots

meta.plot2.sig.bothsexes <- as.data.frame(meta.plot2.sig.malebias)
meta.plot2.sig.bothsexes.b <- gather(meta.plot2.sig.bothsexes, key = sex, value = percent, malepercent:femalepercent, factor_key = TRUE)

# create new sample size variable

meta.plot2.sig.bothsexes.b$samplesize <- with(meta.plot2.sig.bothsexes.b, ifelse(sex == "malepercent", male_sig, female_sig))

# Plot Fig2 all significant results (CI not overlapping zero):
# Several grouing terms are added post-hoc (with no data to display): no significant lnCVR for 'Hearing' in either sex; no sig. male-biased lnCVR for 'Immunology' and 'Eye, and no significant male-biased lnVR for 'Eye'.

malebias_Fig2_sigtraits <-
  ggplot(meta.plot2.sig.bothsexes.b) +
  aes(x = GroupingTerm, y = percent, fill = sex) +
  geom_col() +
  geom_hline(yintercept = 50, linetype = "dashed", color = "gray40") +
  geom_text(
    data = subset(meta.plot2.sig.bothsexes.b, samplesize != 0), aes(label = samplesize), position = position_stack(vjust = .5),
    color = "white", size = 3.5
  ) +
  facet_grid(
    cols = vars(trait), rows = vars(label), labeller = label_wrap_gen(width = 18),
    scales = "free", space = "free"
  ) +
  scale_fill_brewer(palette = "Set2") +
  theme_bw(base_size = 18) +
  theme(
    strip.text.y = element_text(angle = 270, size = 10, margin = margin(t = 15, r = 15, b = 15, l = 15)),
    strip.text.x = element_text(size = 12),
    strip.background = element_rect(colour = NULL, linetype = "blank", fill = "gray90"),
    text = element_text(size = 14),
    panel.spacing = unit(0.5, "lines"),
    panel.border = element_blank(),
    axis.line = element_line(),
    panel.grid.major.x = element_line(linetype = "solid", colour = "gray95"),
    panel.grid.major.y = element_line(linetype = "solid", color = "gray95"),
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank(),
    legend.position = "none",
    axis.title.x = element_blank(),
    axis.title.y = element_blank()
  ) +
  coord_flip()

Preparation for Plots on significant sex-bias (Second-order meta analysis results

Figure 5 B - traits with CI not overlapping 0

Prepare data create column with 1= different from zero, 0= zero included in CI #### Male-biased (significant) traits

meta.male.plot3.sig <- metacombo %>%
  mutate(
    sigCVR = ifelse(lnCVR_lower > 0, 1, 0),
    sigVR = ifelse(lnVR_lower > 0, 1, 0),
    sigRR = ifelse(lnRR_lower > 0, 1, 0)
  )

# Significant subset for lnCVR
metacombo_male.plot3.CVR <- meta.male.plot3.sig %>%
  filter(sigCVR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_male.plot3.CVR.all <- meta.male.plot3.sig %>%
  filter(sigCVR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# Significant subset for lnVR
metacombo_male.plot3.VR <- meta.male.plot3.sig %>%
  filter(sigVR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_male.plot3.VR.all <- meta.male.plot3.sig %>%
  filter(sigVR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# Significant subset for lnRR
metacombo_male.plot3.RR <- meta.male.plot3.sig %>%
  filter(sigRR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_male.plot3.RR.all <- meta.male.plot3.sig %>%
  filter(sigRR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# **Final fixed effects meta-analyses within grouping terms, with SE of the estimate

plot3.male.meta.CVR <- metacombo_male.plot3.CVR %>%
  mutate(model_lnCVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnCVR, sei = (.x$lnCVR_upper - .x$lnCVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.male.meta.VR <- metacombo_male.plot3.VR %>%
  mutate(model_lnVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnVR, sei = (.x$lnVR_upper - .x$lnVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.male.meta.RR <- metacombo_male.plot3.RR %>%
  mutate(model_lnRR = map(data, ~ metafor::rma.uni(
    yi = .x$lnRR, sei = (.x$lnRR_upper - .x$lnRR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

# Across all grouping terms #

plot3.male.meta.CVR.all <- metacombo_male.plot3.CVR.all %>%
  mutate(model_lnCVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnCVR, sei = (.x$lnCVR_upper - .x$lnCVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.male.meta.CVR.all <- plot3.male.meta.CVR.all %>% mutate(GroupingTerm = "All")

plot3.male.meta.VR.all <- metacombo_male.plot3.VR.all %>%
  mutate(model_lnVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnVR, sei = (.x$lnVR_upper - .x$lnVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.male.meta.VR.all <- plot3.male.meta.VR.all %>% mutate(GroupingTerm = "All")

plot3.male.meta.RR.all <- metacombo_male.plot3.RR.all %>%
  mutate(model_lnRR = map(data, ~ metafor::rma.uni(
    yi = .x$lnRR, sei = (.x$lnRR_upper - .x$lnRR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.male.meta.RR.all <- plot3.male.meta.RR.all %>% mutate(GroupingTerm = "All")

# Combine with separate grouping term results

plot3.male.meta.CVR <- bind_rows(plot3.male.meta.CVR, plot3.male.meta.CVR.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
plot3.male.meta.VR <- bind_rows(plot3.male.meta.VR, plot3.male.meta.VR.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
plot3.male.meta.RR <- bind_rows(plot3.male.meta.RR, plot3.male.meta.RR.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
# **Re-structure data for each grouping term; delete un-used variables

plot3.male.meta.CVR.b <- as.data.frame(plot3.male.meta.CVR %>% group_by(GroupingTerm) %>%
  mutate(
    lnCVR = map_dbl(model_lnCVR, pluck(2)), lnCVR_lower = map_dbl(model_lnCVR, pluck(6)),
    lnCVR_upper = map_dbl(model_lnCVR, pluck(7)), lnCVR_se = map_dbl(model_lnCVR, pluck(3))
  ))[, c(1, 4:7)]
add.row.hearing <- as.data.frame(t(c("Hearing", NA, NA, NA, NA))) %>% setNames(names(plot3.male.meta.CVR.b))

plot3.male.meta.CVR.b <- bind_rows(plot3.male.meta.CVR.b, add.row.hearing)
binding character and factor vector, coercing into character vector
plot3.male.meta.CVR.b <- plot3.male.meta.CVR.b[order(plot3.male.meta.CVR.b$GroupingTerm), ]

plot3.male.meta.VR.b <- as.data.frame(plot3.male.meta.VR %>% group_by(GroupingTerm) %>%
  mutate(
    lnVR = map_dbl(model_lnVR, pluck(2)), lnVR_lower = map_dbl(model_lnVR, pluck(6)),
    lnVR_upper = map_dbl(model_lnVR, pluck(7)), lnVR_se = map_dbl(model_lnVR, pluck(3))
  ))[, c(1, 4:7)]
plot3.male.meta.VR.b <- plot3.male.meta.VR.b[order(plot3.male.meta.VR.b$GroupingTerm), ]

plot3.male.meta.RR.b <- as.data.frame(plot3.male.meta.RR %>% group_by(GroupingTerm) %>%
  mutate(
    lnRR = map_dbl(model_lnRR, pluck(2)), lnRR_lower = map_dbl(model_lnRR, pluck(6)),
    lnRR_upper = map_dbl(model_lnRR, pluck(7)), lnRR_se = map_dbl(model_lnRR, pluck(3))
  ))[, c(1, 4:7)]
plot3.male.meta.RR.b <- plot3.male.meta.RR.b[order(plot3.male.meta.RR.b$GroupingTerm), ]

overall.male.plot3 <- full_join(plot3.male.meta.CVR.b, plot3.male.meta.VR.b)
Joining, by = "GroupingTerm"
overall.male.plot3 <- full_join(overall.male.plot3, plot3.male.meta.RR.b)
Joining, by = "GroupingTerm"
overall.male.plot3$GroupingTerm <- factor(overall.male.plot3$GroupingTerm, levels = c("Behaviour", "Morphology", "Metabolism", "Physiology", "Immunology", "Hematology", "Heart", "Hearing", "Eye", "All"))
overall.male.plot3$GroupingTerm <- factor(overall.male.plot3$GroupingTerm, rev(levels(overall.male.plot3$GroupingTerm)))

# add missing GroupingTerms for plot
overall.male.plot3 <- add_row(overall.male.plot3, GroupingTerm = "Behaviour")
overall.male.plot3 <- add_row(overall.male.plot3, GroupingTerm = "Immunology")
overall.male.plot3 <- add_row(overall.male.plot3, GroupingTerm = "Eye")

overall.male.plot3$GroupingTerm <- factor(overall.male.plot3$GroupingTerm, levels = c("Behaviour", "Morphology", "Metabolism", "Physiology", "Immunology", "Hematology", "Heart", "Hearing", "Eye", "All"))
overall.male.plot3$GroupingTerm <- factor(overall.male.plot3$GroupingTerm, rev(levels(overall.male.plot3$GroupingTerm)))

# str(overall.male.plot3)

Restructure MALE data for plotting

overall3.male.sig <- gather(overall.male.plot3, parameter, value, c(lnCVR, lnRR), factor_key = TRUE) # lnVR,

lnCVR.ci <- overall3.male.sig %>%
  filter(parameter == "lnCVR") %>%
  mutate(ci.low = lnCVR_lower, ci.high = lnCVR_upper)
# lnVR.ci <- overall3.male.sig  %>% filter(parameter == "lnVR") %>% mutate(ci.low = lnVR_lower, ci.high = lnVR_upper)
lnRR.ci <- overall3.male.sig %>%
  filter(parameter == "lnRR") %>%
  mutate(ci.low = lnRR_lower, ci.high = lnRR_upper)

overall4.male.sig <- bind_rows(lnCVR.ci, lnRR.ci) %>% select(GroupingTerm, parameter, value, ci.low, ci.high) # lnVR.ci,

overall4.male.sig$label <- "CI not overlapping zero"

Plot Fig5b all significant results (CI not overlapping zero) for males


Metameta_Fig3_male.sig <- overall4.male.sig %>%
  ggplot(aes(y = GroupingTerm, x = value)) +
  geom_errorbarh(aes(
    xmin = ci.low,
    xmax = ci.high
  ),
  height = 0.1, show.legend = FALSE
  ) +
  geom_point(aes(shape = parameter),
    fill = "mediumaquamarine", color = "mediumaquamarine", size = 2.2,
    show.legend = FALSE
  ) +
  scale_x_continuous(
    limits = c(0, 0.4),
    breaks = c(0, 0.3),
    name = "Effect size"
  ) +
  geom_vline(
    xintercept = 0,
    color = "black",
    linetype = "dashed"
  ) +
  facet_grid(
    cols = vars(parameter), rows = vars(label),
    labeller = label_wrap_gen(width = 23),
    scales = "free",
    space = "free"
  ) +
  theme_bw() +
  theme(
    strip.text.y = element_text(angle = 270, size = 10, margin = margin(t = 15, r = 15, b = 15, l = 15)),
    strip.text.x = element_text(size = 12),
    strip.background = element_rect(colour = NULL, linetype = "blank", fill = "gray90"),
    text = element_text(size = 14),
    panel.spacing = unit(0.5, "lines"),
    panel.border = element_blank(),
    axis.line = element_line(),
    panel.grid.major.x = element_line(linetype = "solid", colour = "gray95"),
    panel.grid.major.y = element_line(linetype = "solid", color = "gray95"),
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank(),
    legend.title = element_blank(),
    axis.title.x = element_blank(),
    axis.title.y = element_blank()
  )

# Metameta_Fig3_male.sig

Female part, significant traits

Female Fig5B sig

Prepare data for traits with CI not overlapping 0 create column with 1= different from zero, 0= zero included in CI


# female-biased traits

meta.female.plot3.sig <- metacombo %>%
  mutate(
    sigCVR = ifelse(lnCVR_upper < 0, 1, 0),
    sigVR = ifelse(lnVR_upper < 0, 1, 0),
    sigRR = ifelse(lnRR_upper < 0, 1, 0)
  )

# Significant subset for lnCVR

metacombo_female.plot3.CVR <- meta.female.plot3.sig %>%
  filter(sigCVR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_female.plot3.CVR.all <- meta.female.plot3.sig %>%
  filter(sigCVR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# Significant subset for lnVR

metacombo_female.plot3.VR <- meta.female.plot3.sig %>%
  filter(sigVR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_female.plot3.VR.all <- meta.female.plot3.sig %>%
  filter(sigVR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# Significant subset for lnRR

metacombo_female.plot3.RR <- meta.female.plot3.sig %>%
  filter(sigRR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_female.plot3.RR.all <- meta.female.plot3.sig %>%
  filter(sigRR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# **Final fixed effects meta-analyses within grouping terms, with SE of the estimate

plot3.female.meta.CVR <- metacombo_female.plot3.CVR %>%
  mutate(model_lnCVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnCVR, sei = (.x$lnCVR_upper - .x$lnCVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.female.meta.VR <- metacombo_female.plot3.VR %>%
  mutate(model_lnVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnVR, sei = (.x$lnVR_upper - .x$lnVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.female.meta.RR <- metacombo_female.plot3.RR %>%
  mutate(model_lnRR = map(data, ~ metafor::rma.uni(
    yi = .x$lnRR, sei = (.x$lnRR_upper - .x$lnRR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

# Across all grouping terms #

plot3.female.meta.CVR.all <- metacombo_female.plot3.CVR.all %>%
  mutate(model_lnCVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnCVR, sei = (.x$lnCVR_upper - .x$lnCVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.female.meta.CVR.all <- plot3.female.meta.CVR.all %>% mutate(GroupingTerm = "All")

plot3.female.meta.VR.all <- metacombo_female.plot3.VR.all %>%
  mutate(model_lnVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnVR, sei = (.x$lnVR_upper - .x$lnVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.female.meta.VR.all <- plot3.female.meta.VR.all %>% mutate(GroupingTerm = "All")

plot3.female.meta.RR.all <- metacombo_female.plot3.RR.all %>%
  mutate(model_lnRR = map(data, ~ metafor::rma.uni(
    yi = .x$lnRR, sei = (.x$lnRR_upper - .x$lnRR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.female.meta.RR.all <- plot3.female.meta.RR.all %>% mutate(GroupingTerm = "All")

# Combine with separate grouping term results

plot3.female.meta.CVR <- bind_rows(plot3.female.meta.CVR, plot3.female.meta.CVR.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
plot3.female.meta.VR <- bind_rows(plot3.female.meta.VR, plot3.female.meta.VR.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
plot3.female.meta.RR <- bind_rows(plot3.female.meta.RR, plot3.female.meta.RR.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
# **Re-structure data for each grouping term; delete un-used variables

plot3.female.meta.CVR.b <- as.data.frame(plot3.female.meta.CVR %>% group_by(GroupingTerm) %>%
  mutate(
    lnCVR = map_dbl(model_lnCVR, pluck(2)), lnCVR_lower = map_dbl(model_lnCVR, pluck(6)),
    lnCVR_upper = map_dbl(model_lnCVR, pluck(7)), lnCVR_se = map_dbl(model_lnCVR, pluck(3))
  ))[, c(1, 4:7)]

add.row.hearing <- as.data.frame(t(c("Hearing", NA, NA, NA, NA))) %>% setNames(names(plot3.female.meta.CVR.b))

plot3.female.meta.CVR.b <- bind_rows(plot3.female.meta.CVR.b, add.row.hearing)
binding character and factor vector, coercing into character vector
plot3.female.meta.CVR.b <- plot3.female.meta.CVR.b[order(plot3.female.meta.CVR.b$GroupingTerm), ]

plot3.female.meta.VR.b <- as.data.frame(plot3.female.meta.VR %>% group_by(GroupingTerm) %>%
  mutate(
    lnVR = map_dbl(model_lnVR, pluck(2)), lnVR_lower = map_dbl(model_lnVR, pluck(6)),
    lnVR_upper = map_dbl(model_lnVR, pluck(7)), lnVR_se = map_dbl(model_lnVR, pluck(3))
  ))[, c(1, 4:7)]

plot3.female.meta.VR.b <- plot3.female.meta.VR.b[order(plot3.female.meta.VR.b$GroupingTerm), ]

plot3.female.meta.RR.b <- as.data.frame(plot3.female.meta.RR %>% group_by(GroupingTerm) %>%
  mutate(
    lnRR = map_dbl(model_lnRR, pluck(2)), lnRR_lower = map_dbl(model_lnRR, pluck(6)),
    lnRR_upper = map_dbl(model_lnRR, pluck(7)), lnRR_se = map_dbl(model_lnRR, pluck(3))
  ))[, c(1, 4:7)]

plot3.female.meta.RR.b <- plot3.female.meta.RR.b[order(plot3.female.meta.RR.b$GroupingTerm), ]

overall.female.plot3 <- full_join(plot3.female.meta.CVR.b, plot3.female.meta.VR.b)
Joining, by = "GroupingTerm"
overall.female.plot3 <- full_join(overall.female.plot3, plot3.female.meta.RR.b)
Joining, by = "GroupingTerm"
overall.female.plot3$GroupingTerm <- factor(overall.female.plot3$GroupingTerm, levels = c("Behaviour", "Morphology", "Metabolism", "Physiology", "Immunology", "Hematology", "Heart", "Hearing", "Eye", "All"))
overall.female.plot3$GroupingTerm <- factor(overall.female.plot3$GroupingTerm, rev(levels(overall.female.plot3$GroupingTerm)))

Restructure data for plotting

overall3.female.sig <- gather(overall.female.plot3, parameter, value, c(lnCVR, lnRR), factor_key = TRUE) # lnVR,

lnCVR.ci <- overall3.female.sig %>%
  filter(parameter == "lnCVR") %>%
  mutate(ci.low = lnCVR_lower, ci.high = lnCVR_upper)
# lnVR.ci <- overall3.female.sig  %>% filter(parameter == "lnVR") %>% mutate(ci.low = lnVR_lower, ci.high = lnVR_upper)
lnRR.ci <- overall3.female.sig %>%
  filter(parameter == "lnRR") %>%
  mutate(ci.low = lnRR_lower, ci.high = lnRR_upper)

overall4.female.sig <- bind_rows(lnCVR.ci, lnRR.ci) %>% select(GroupingTerm, parameter, value, ci.low, ci.high) # lnVR.ci,

overall4.female.sig$label <- "CI not overlapping zero"

Plotting Fig5B all significant results (CI not overlapping zero, female )


Metameta_Fig3_female.sig <- overall4.female.sig %>%
  ggplot(aes(y = GroupingTerm, x = value)) +
  geom_errorbarh(aes(
    xmin = ci.low,
    xmax = ci.high
  ),
  height = 0.1, show.legend = FALSE
  ) +
  geom_point(aes(shape = parameter),
    fill = "salmon1", color = "salmon1", size = 2.2,
    show.legend = FALSE
  ) +
  scale_x_continuous(
    limits = c(-0.4, 0),
    breaks = c(-0.3, 0),
    name = "Effect size"
  ) +
  geom_vline(
    xintercept = 0,
    color = "black",
    linetype = "dashed"
  ) +
  facet_grid(
    cols = vars(parameter), # rows = vars(label),
    # labeller = label_wrap_gen(width = 23),
    scales = "free",
    space = "free"
  ) +
  theme_bw() +
  theme(
    strip.text.y = element_text(angle = 270, size = 10, margin = margin(t = 15, r = 15, b = 15, l = 15)),
    strip.text.x = element_text(size = 12),
    strip.background = element_rect(colour = NULL, linetype = "blank", fill = "gray90"),
    text = element_text(size = 14),
    panel.spacing = unit(0.5, "lines"),
    panel.border = element_blank(),
    axis.line = element_line(),
    panel.grid.major.x = element_line(linetype = "solid", colour = "gray95"),
    panel.grid.major.y = element_line(linetype = "solid", color = "gray95"),
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank(),
    legend.title = element_blank(),
    axis.title.x = element_blank(),
    axis.title.y = element_blank()
  )

# Metameta_Fig3_female.sig #(Figure 5B left panel)

JOIN!!! CODE MISSING??

Supplemental Plots

Figure S1

Including lnVR

Count data, including lnVR (Fig S1 panel A)

# *Prepare data for all traits

meta.plot2.all <- meta_clean %>%
  select(lnCVR, lnVR, lnRR, GroupingTerm) %>%
  arrange(GroupingTerm)

meta.plot2.all.bS1 <- gather(meta.plot2.all, trait, value, c(lnCVR, lnVR, lnRR))

meta.plot2.all.bS1$trait <- factor(meta.plot2.all.bS1$trait, levels = c("lnCVR", "lnVR", "lnRR"))

meta.plot2.all.cS1 <- meta.plot2.all.bS1 %>%
  group_by_at(vars(trait, GroupingTerm)) %>%
  summarise(
    malebias = sum(value > 0), femalebias = sum(value <= 0), total = malebias + femalebias,
    malepercent = malebias * 100 / total, femalepercent = femalebias * 100 / total
  )

meta.plot2.all.cS1$label <- "All traits"

# restructure to create stacked bar plots

meta.plot2.all.dS1 <- as.data.frame(meta.plot2.all.cS1)
meta.plot2.all.eS1 <- gather(meta.plot2.all.dS1, key = sex, value = percent, malepercent:femalepercent, factor_key = TRUE)

# create new sample size variable

meta.plot2.all.eS1$samplesize <- with(meta.plot2.all.eS1, ifelse(sex == "malepercent", malebias, femalebias))

malebias_FigS1_alltraits <-
  ggplot(meta.plot2.all.eS1) +
  aes(x = GroupingTerm, y = percent, fill = sex) +
  geom_col() +
  geom_hline(yintercept = 50, linetype = "dashed", color = "gray40") +
  geom_text(
    data = subset(meta.plot2.all.eS1, samplesize != 0), aes(label = samplesize), position = position_stack(vjust = .5),
    color = "white", size = 3.5
  ) +
  facet_grid(
    cols = vars(trait), rows = vars(label), labeller = label_wrap_gen(width = 18),
    scales = "free", space = "free"
  ) +
  scale_fill_brewer(palette = "Set2") +
  theme_bw(base_size = 18) +
  theme(
    strip.text.y = element_text(angle = 270, size = 10, margin = margin(t = 15, r = 15, b = 15, l = 15)),
    strip.text.x = element_text(size = 12),
    strip.background = element_rect(colour = NULL, linetype = "blank", fill = "gray90"),
    text = element_text(size = 14),
    panel.spacing = unit(0.5, "lines"),
    panel.border = element_blank(),
    axis.line = element_line(),
    panel.grid.major.x = element_line(linetype = "solid", colour = "gray95"),
    panel.grid.major.y = element_line(linetype = "solid", color = "gray95"),
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank(),
    legend.position = "none",
    axis.title.x = element_blank(),
    axis.title.y = element_blank()
  ) +
  coord_flip()

# malebias_FigS1_alltraits     #(panel A in Figure S1)

Overall results of second order meta analysis, INCLUDING VR

Restructure data for plotting

Restructure MALE data for plotting

overall3.male.sigS <- gather(overall.male.plot3, parameter, value, c(lnCVR, lnVR, lnRR), factor_key = TRUE)

lnCVR.ci <- overall3.male.sigS %>%
  filter(parameter == "lnCVR") %>%
  mutate(ci.low = lnCVR_lower, ci.high = lnCVR_upper)
lnVR.ci <- overall3.male.sigS %>%
  filter(parameter == "lnVR") %>%
  mutate(ci.low = lnVR_lower, ci.high = lnVR_upper)
lnRR.ci <- overall3.male.sigS %>%
  filter(parameter == "lnRR") %>%
  mutate(ci.low = lnRR_lower, ci.high = lnRR_upper)

overall4.male.sigS <- bind_rows(lnCVR.ci, lnVR.ci, lnRR.ci) %>% select(GroupingTerm, parameter, value, ci.low, ci.high)

overall4.male.sigS$label <- "CI not overlapping zero"

# Data are restructured, and grouping terms are being re-ordered

overall3S <- gather(overall2, parameter, value, c(lnCVR, lnVR, lnRR), factor_key = TRUE)

lnCVR.ci <- overall3S %>%
  filter(parameter == "lnCVR") %>%
  mutate(ci.low = lnCVR_lower, ci.high = lnCVR_upper)
lnVR.ci <- overall3S %>%
  filter(parameter == "lnVR") %>%
  mutate(ci.low = lnVR_lower, ci.high = lnVR_upper)
lnRR.ci <- overall3S %>%
  filter(parameter == "lnRR") %>%
  mutate(ci.low = lnRR_lower, ci.high = lnRR_upper)

overall4S <- bind_rows(lnCVR.ci, lnVR.ci, lnRR.ci) %>% select(GroupingTerm, parameter, value, ci.low, ci.high)

# re-order Grouping Terms

overall4S$GroupingTerm <- factor(overall4S$GroupingTerm, levels = c("Behaviour", "Morphology", "Metabolism", "Physiology", "Immunology", "Hematology", "Heart", "Hearing", "Eye", "All"))
overall4S$GroupingTerm <- factor(overall4S$GroupingTerm, rev(levels(overall4S$GroupingTerm)))
overall4S$label <- "All traits"

Preparation for plot, including lnVR

Preparation: Sub-Plot for Figure S1: all traits (S1 B)

Metameta_FigS1_alltraits <- overall4S %>%

  ggplot(aes(y = GroupingTerm, x = value)) +
  geom_errorbarh(aes(
    xmin = ci.low,
    xmax = ci.high
  ),
  height = 0.1, show.legend = FALSE
  ) +
  geom_point(aes(shape = parameter),
    fill = "black",
    color = "black", size = 2.2,
    show.legend = FALSE
  ) +
  scale_x_continuous(
    limits = c(-0.24, 0.25),
    breaks = c(-0.2, -0.1, 0, 0.1, 0.2),
    name = "Effect size"
  ) +
  geom_vline(
    xintercept = 0,
    color = "black",
    linetype = "dashed"
  ) +
  facet_grid(
    cols = vars(parameter), rows = vars(label),
    labeller = label_wrap_gen(width = 23),
    scales = "free",
    space = "free"
  ) +
  theme_bw() +
  theme(
    strip.text.y = element_text(angle = 270, size = 10, margin = margin(t = 15, r = 15, b = 15, l = 15)),
    strip.text.x = element_text(size = 12),
    strip.background = element_rect(colour = NULL, linetype = "blank", fill = "gray90"),
    text = element_text(size = 14),
    panel.spacing = unit(0.5, "lines"),
    panel.border = element_blank(),
    axis.line = element_line(),
    panel.grid.major.x = element_line(linetype = "solid", colour = "gray95"),
    panel.grid.major.y = element_line(linetype = "solid", color = "gray95"),
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank(),
    legend.title = element_blank(),
    axis.title.x = element_text(hjust = 0.5, size = 14),
    axis.title.y = element_blank()
  )

# Metameta_FigS1_alltraits

Heterogeneity

The analysis for heterogeneity follows the workflow of the above steps for the different meta-analyses. However, in the initial meta-analysis we extract sigma^2 and errors for mouse strains and centers (Institutions).

results.allhetero.grouping <- as.data.frame(cbind(c(1:n), matrix(rep(0, n * 30), ncol = 30)))
names(results.allhetero.grouping) <- c(
  "id", "sigma2_strain.CVR", "sigma2_center.CVR", "sigma2_error.CVR", "s.nlevels.strain.CVR",
  "s.nlevels.center.CVR", "s.nlevels.error.CVR", "sigma2_strain.VR", "sigma2_center.VR", "sigma2_error.VR", "s.nlevels.strain.VR",
  "s.nlevels.center.VR", "s.nlevels.error.VR", "sigma2_strain.RR", "sigma2_center.RR", "sigma2_error.RR", "s.nlevels.strain.RR",
  "s.nlevels.center.RR", "s.nlevels.error.RR", "lnCVR", "lnCVR_lower", "lnCVR_upper", "lnCVR_se", "lnVR", "lnVR_lower", "lnVR_upper",
  "lnVR_se", "lnRR", "lnRR_lower", "lnRR_upper", "lnRR_se"
)

LOOP Parameters to extract from metafor (sigma2’s, s.nlevels)


for (t in 1:n) {
  tryCatch(
    {
      data_par_age <- data_subset_parameterid_individual_by_age(data, t, age_min = 0, age_center = 100)

      population_stats <- calculate_population_stats(data_par_age)

      results <- create_meta_analysis_effect_sizes(population_stats)

      # lnCVR, logaritm of the ratio of male and female coefficients of variance

      cvr. <- metafor::rma.mv(yi = effect_size_CVR, V = sample_variance_CVR, random = list(
        ~ 1 | strain_name, ~ 1 | production_center,
        ~ 1 | err
      ), control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), data = results)
      results.allhetero.grouping[t, 2] <- cvr.$sigma2[1]
      results.allhetero.grouping[t, 3] <- cvr.$sigma2[2]
      results.allhetero.grouping[t, 4] <- cvr.$sigma2[3]
      results.allhetero.grouping[t, 5] <- cvr.$s.nlevels[1]
      results.allhetero.grouping[t, 6] <- cvr.$s.nlevels[2]
      results.allhetero.grouping[t, 7] <- cvr.$s.nlevels[3]
      results.allhetero.grouping[t, 20] <- cvr.$b
      results.allhetero.grouping[t, 21] <- cvr.$ci.lb
      results.allhetero.grouping[t, 22] <- cvr.$ci.ub
      results.allhetero.grouping[t, 23] <- cvr.$se

      # lnVR, male to female variability ratio (logarithm of male and female standard deviations)

      vr. <- metafor::rma.mv(yi = effect_size_VR, V = sample_variance_VR, random = list(
        ~ 1 | strain_name, ~ 1 | production_center,
        ~ 1 | err
      ), control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), data = results)
      results.allhetero.grouping[t, 8] <- vr.$sigma2[1]
      results.allhetero.grouping[t, 9] <- vr.$sigma2[2]
      results.allhetero.grouping[t, 10] <- vr.$sigma2[3]
      results.allhetero.grouping[t, 11] <- vr.$s.nlevels[1]
      results.allhetero.grouping[t, 12] <- vr.$s.nlevels[2]
      results.allhetero.grouping[t, 13] <- vr.$s.nlevels[3]
      results.allhetero.grouping[t, 24] <- vr.$b
      results.allhetero.grouping[t, 25] <- vr.$ci.lb
      results.allhetero.grouping[t, 26] <- vr.$ci.ub
      results.allhetero.grouping[t, 27] <- vr.$se

      # lnRR, response ratio (logarithm of male and female means)

      rr. <- metafor::rma.mv(yi = effect_size_RR, V = sample_variance_RR, random = list(
        ~ 1 | strain_name, ~ 1 | production_center,
        ~ 1 | err
      ), control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), data = results)
      results.allhetero.grouping[t, 14] <- rr.$sigma2[1]
      results.allhetero.grouping[t, 15] <- rr.$sigma2[2]
      results.allhetero.grouping[t, 16] <- rr.$sigma2[3]
      results.allhetero.grouping[t, 17] <- rr.$s.nlevels[1]
      results.allhetero.grouping[t, 18] <- rr.$s.nlevels[2]
      results.allhetero.grouping[t, 19] <- rr.$s.nlevels[3]
      results.allhetero.grouping[t, 28] <- rr.$b
      results.allhetero.grouping[t, 29] <- rr.$ci.lb
      results.allhetero.grouping[t, 30] <- rr.$ci.ub
      results.allhetero.grouping[t, 31] <- rr.$se
    },
    error = function(e) {
      cat("ERROR :", conditionMessage(e), "\n")
    }
  )
}
ERROR : Optimizer (optim) did not achieve convergence (convergence = 10). 
Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.There are outcomes with non-positive sampling variances.'V' appears to be not positive definite.
ERROR : Optimizer (optim) did not achieve convergence (convergence = 10). 
Rows with NAs omitted from model fitting.
ERROR : NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.
ERROR : NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.
ERROR : NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.
ERROR : NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.
ERROR : NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.
ERROR : NA/NaN/Inf in 'y' 
Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.There are outcomes with non-positive sampling variances.'V' appears to be not positive definite.Rows with NAs omitted from model fitting.
ERROR : NA/NaN/Inf in 'y' 
Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Single-level factor(s) found in 'random' argument. Corresponding 'sigma2' value(s) fixed to 0.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.There are outcomes with non-positive sampling variances.'V' appears to be not positive definite.Rows with NAs omitted from model fitting.Rows with NAs omitted from model fitting.There are outcomes with non-positive sampling variances.'V' appears to be not positive definite.Rows with NAs omitted from model fitting.
ERROR : NA/NaN/Inf in 'y' 

Exclude traits, merge datasets

results.allhetero.grouping2 <- results.allhetero.grouping[results.allhetero.grouping$s.nlevels.strain.VR != 0, ]
# nrow(results.allhetero.grouping2) #218  SZ 223???

Merge data sets containing metafor results with procedure etc. names

# procedures <- read.csv(here("export", "procedures.csv"))

results.allhetero.grouping2$parameter_group <- data$parameter_group[match(results.allhetero.grouping2$id, data$id)]
results.allhetero.grouping2$procedure <- data$procedure_name[match(results.allhetero.grouping2$id, data$id)]

results.allhetero.grouping2$GroupingTerm <- procedures$GroupingTerm[match(results.allhetero.grouping2$procedure, procedures$procedure)]
results.allhetero.grouping2$parameter_name <- data$parameter_name[match(results.allhetero.grouping2$id, data$id)]

Correlated parameters

##FELIX : check? numbers don’t add up??

metahetero1 <- results.allhetero.grouping2
# length(unique(metahetero1$procedure)) #18  SZ 19
# length(unique(metahetero1$GroupingTerm)) #9 Sz ok
# length(unique(metahetero1$parameter_group)) # 149 SZ 152
# length(unique(metahetero1$parameter_name)) #218  SZ 223

# Count of number of parameter names (correlated sub-traits) in each parameter group (par_group_size)

metahetero1b <-
  metahetero1 %>%
  group_by(parameter_group) %>%
  mutate(par_group_size = n_distinct(parameter_name))

metahetero1$par_group_size <- metahetero1b$par_group_size[match(metahetero1$parameter_group, metahetero1b$parameter_group)]

# Create subsets with > 1 count (par_group_size > 1)

metahetero1_sub <- subset(metahetero1, par_group_size > 1) # 90 observations
# str(metahetero1_sub)
# metahetero1_sub$sampleSize <- as.numeric(metahetero1_sub$sampleSize) #from previous analysis? don't think is used: : delete in final version

# Nest data

n_count. <- metahetero1_sub %>%
  group_by(parameter_group) %>%
  # mutate(raw_N = sum(sampleSize)) %>%  #don't think is necessary: delete in final version
  nest()

# meta-analysis preparation

model_count. <- n_count. %>%
  mutate(
    model_lnRR = map(data, ~ robu(.x$lnRR ~ 1,
      data = .x, studynum = .x$id, modelweights = c("CORR"), rho = 0.8,
      small = TRUE, var.eff.size = (.x$lnRR_se)^2
    )),
    model_lnVR = map(data, ~ robu(.x$lnVR ~ 1,
      data = .x, studynum = .x$id, modelweights = c("CORR"), rho = 0.8,
      small = TRUE, var.eff.size = (.x$lnVR_se)^2
    )),
    model_lnCVR = map(data, ~ robu(.x$lnCVR ~ 1,
      data = .x, studynum = .x$id, modelweights = c("CORR"), rho = 0.8,
      small = TRUE, var.eff.size = (.x$lnCVR_se)^2
    ))
  )


# Robumeta object details:
# str(model_count.$model_lnCVR[[1]])

## *Perform meta-analyses on correlated sub-traits, using robumeta
 # Susi / FELIX: what's this below?
# Shinichi: We think we want to use these for further analyses:
# residual variance: as.numeric(robu_fit$mod_info$term1)     (same as 'mod_info$tau.sq')
# sample size: robu_fit$N

## **Extract and save parameter estimates

# Felix: doesn't work , error message:
#!!!!!!!!!!! ERROR!!!!!!!!!!!!!!!!!!!!
#Error: Column `parameter_group` can't be modified because it's a grouping variable

count_fun. <- function(mod_sub) {
  return(c(as.numeric(mod_sub$mod_info$term1), mod_sub$N))
}

robusub_RR. <- model_count. %>%
  transmute(parameter_group, estimatelnRR = map(model_lnRR, count_fun.)) %>%
  mutate(r = map(estimatelnRR, ~ data.frame(t(.)))) %>%
  unnest(r) %>%
  select(-estimatelnRR) %>%
  purrr::set_names(c("parameter_group", "var.RR", "N.RR"))
Error: Column `parameter_group` can't be modified because it's a grouping variable

Merge the two data sets (the new [robu_all.] and the initial [uncorrelated sub-traits with count = 1])

In this step, we
1) merge the N from robumeta and the N from metafor (s.nlevels.error) together into the same columns (N.RR, N.VR, N.CVR) 2) calculate the total variance for metafor models as the sum of random effect variances and the residual error, then add in the same columns together with the residual variances from robumeta

metahetero_all <- metahetero1 %>%
  filter(par_group_size == 1) %>%
  as_tibble()
metahetero_all$N.RR <- metahetero_all$s.nlevels.error.RR
metahetero_all$N.CVR <- metahetero_all$s.nlevels.error.CVR
metahetero_all$N.VR <- metahetero_all$s.nlevels.error.VR
metahetero_all$var.RR <- log(sqrt(metahetero_all$sigma2_strain.RR + metahetero_all$sigma2_center.RR + metahetero_all$sigma2_error.RR))
metahetero_all$var.VR <- log(sqrt(metahetero_all$sigma2_strain.VR + metahetero_all$sigma2_center.VR + metahetero_all$sigma2_error.VR))
metahetero_all$var.CVR <- log(sqrt(metahetero_all$sigma2_strain.CVR + metahetero_all$sigma2_center.CVR + metahetero_all$sigma2_error.CVR))
# str(metahetero_all)
# str(robu_all.)

metahetero_all <- metahetero_all %>% mutate(
  var.RR = if_else(var.RR == -Inf, -7, var.RR),
  var.VR = if_else(var.VR == -Inf, -5, var.VR),
  var.CVR = if_else(var.CVR == -Inf, -6, var.CVR)
)

# **Combine data
## Step1
combinedmetahetero <- bind_rows(robu_all., metahetero_all)
Error in dots_values(...) : object 'robu_all.' not found

Meta-analysis of heterogeneity

## Perform meta-meta-analysis (3 for each of the 9 grouping terms: var.CVR, var.VR, var.RR)

metacombohetero_final <- metacombohetero %>%
  group_by(GroupingTerm) %>%
  nest()
Error in eval(lhs, parent, parent) : object 'metacombohetero' not found

Heterogeneity PLOT

Restructure data for plotting

Plot S1 C (Second-order meta analysis on heterogeneity)

Combined Figure S1: overall Count data, Meta anlysis results, Heterogeneity)

HeteroS1
Error: object 'HeteroS1' not found

Figure S2

Plot FigS2 all significant results (CI not overlapping zero) for males ### FELIX: “ALL” missing.

Prepare data for traits with effect size ratios > 10% larger in males, supplemental Figure S2

FELIX: “ALL” missing.

This Figure extends Figure 4, as it includes results not only for lnCVR and lnRR but also lnCVR. In addition, we compare two different assessments of sex-bias, significance (CI not overlapping zero) and sex differences in male / female ratios > 10%

Over 10% male bias, count data (first- order metanalysis)

meta.plot2.over10 <- meta_clean %>%
  select(lnCVR, lnVR, lnRR, GroupingTerm) %>%
  arrange(GroupingTerm) 

meta.plot2.over10.b <- gather(meta.plot2.over10, trait, value, c(lnCVR, lnVR, lnRR)) 

meta.plot2.over10.b$trait <- factor(meta.plot2.over10.b$trait, levels = c("lnCVR", "lnVR", "lnRR")) 

meta.plot2.over10.c <- meta.plot2.over10.b %>%
  group_by_at(vars(trait, GroupingTerm)) %>%
  summarise(
    malebias = sum(value > log(11 / 10)), femalebias = sum(value < log(9 / 10)), total = malebias + femalebias,
    malepercent = malebias * 100 / total, femalepercent = femalebias * 100 / total
  )

meta.plot2.over10.c$label <- "Sex difference in m/f ratios > 10%"

# restructure to create stacked bar plots

meta.plot2.over10.c <- as.data.frame(meta.plot2.over10.c)
meta.plot2.over10.d <- gather(meta.plot2.over10.c, key = sex, value = percent, malepercent:femalepercent, factor_key = TRUE)

# create new sample size variable

meta.plot2.over10.d$samplesize <- with(meta.plot2.over10.d, ifelse(sex == "malepercent", malebias, femalebias))

# *Plot Fig2 Sex difference in m/f ratio > 10%
malebias_Fig2_over10 <-
  ggplot(meta.plot2.over10.d) +
  aes(x = GroupingTerm, y = percent, fill = sex) +
  geom_col() +
  geom_hline(yintercept = 50, linetype = "dashed", color = "gray40") +
  geom_text(
    data = subset(meta.plot2.over10.d, samplesize != 0), aes(label = samplesize), position = position_stack(vjust = .5),
    color = "white", size = 3.5
  ) +
  facet_grid(
    cols = vars(trait), rows = vars(label), labeller = label_wrap_gen(width = 18),
    scales = "free", space = "free"
  ) +
  scale_fill_brewer(palette = "Set2") +
  theme_bw(base_size = 18) +
  theme(
    strip.text.y = element_text(angle = 270, size = 10, margin = margin(t = 15, r = 15, b = 15, l = 15)),
    strip.text.x = element_blank(),
    strip.background = element_rect(colour = NULL, linetype = "blank", fill = "gray90"),
    text = element_text(size = 14),
    panel.spacing = unit(0.5, "lines"),
    panel.border = element_blank(),
    axis.line = element_line(),
    panel.grid.major.x = element_line(linetype = "solid", colour = "gray95"),
    panel.grid.major.y = element_line(linetype = "solid", color = "gray95"),
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank(),
    legend.position = "none",
    axis.title.x = element_blank(),
    axis.title.y = element_blank()
  ) +
  coord_flip()

# malebias_Fig2_over10  (supplemental Figure S2)

Fig S2, second-order meta-analysis, male traits

Female Figure, significant traits

Female FigS2 B sig

Prepare data for traits with CI not overlapping 0 create column with 1= different from zero, 0= zero included in CI

Restructure data for plotting

Prepare data for traits with m/f difference > 10%

Create column with 1= larger, 0= difference not larger than 10% between male/female ratios

meta.male.plot3.perc <- metacombo %>%
  mutate(
    percCVR = ifelse(lnCVR > log(11 / 10), 1, 0),
    percVR = ifelse(lnVR > log(11 / 10), 1, 0),
    percRR = ifelse(lnRR > log(11 / 10), 1, 0)
  )

# Significant subset for lnCVR
metacombo_male.plot3.CVR.perc <- meta.male.plot3.perc %>%
  filter(percCVR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_male.plot3.CVR.perc.all <- meta.male.plot3.perc %>%
  filter(percCVR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# Significant subset for lnVR
metacombo_male.plot3.VR.perc <- meta.male.plot3.perc %>%
  filter(percVR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_male.plot3.VR.perc.all <- meta.male.plot3.perc %>%
  filter(percVR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# Significant subset for lnRR
metacombo_male.plot3.RR.perc <- meta.male.plot3.perc %>%
  filter(percRR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_male.plot3.RR.perc.all <- meta.male.plot3.perc %>%
  filter(percRR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# **Final fixed effects meta-analyses within grouping terms and across grouping terms, with SE of the estimate

plot3.male.meta.CVR.perc <- metacombo_male.plot3.CVR.perc %>%
  mutate(model_lnCVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnCVR, sei = (.x$lnCVR_upper - .x$lnCVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.male.meta.VR.perc <- metacombo_male.plot3.VR.perc %>%
  mutate(model_lnVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnVR, sei = (.x$lnVR_upper - .x$lnVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.male.meta.RR.perc <- metacombo_male.plot3.RR.perc %>%
  mutate(model_lnRR = map(data, ~ metafor::rma.uni(
    yi = .x$lnRR, sei = (.x$lnRR_upper - .x$lnRR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

# Across all grouping terms #

plot3.male.meta.CVR.perc.all <- metacombo_male.plot3.CVR.perc.all %>%
  mutate(model_lnCVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnCVR, sei = (.x$lnCVR_upper - .x$lnCVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.male.meta.CVR.perc.all <- plot3.male.meta.CVR.perc.all %>% mutate(GroupingTerm = "All")

plot3.male.meta.VR.perc.all <- metacombo_male.plot3.VR.perc.all %>%
  mutate(model_lnVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnVR, sei = (.x$lnVR_upper - .x$lnVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.male.meta.VR.perc.all <- plot3.male.meta.VR.perc.all %>% mutate(GroupingTerm = "All")

plot3.male.meta.RR.perc.all <- metacombo_male.plot3.RR.perc.all %>%
  mutate(model_lnRR = map(data, ~ metafor::rma.uni(
    yi = .x$lnRR, sei = (.x$lnRR_upper - .x$lnRR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.male.meta.RR.perc.all <- plot3.male.meta.RR.perc.all %>% mutate(GroupingTerm = "All")

# Combine with separate grouping term results

plot3.male.meta.CVR.perc <- bind_rows(plot3.male.meta.CVR.perc, plot3.male.meta.CVR.perc.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
plot3.male.meta.VR.perc <- bind_rows(plot3.male.meta.VR.perc, plot3.male.meta.VR.perc.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
plot3.male.meta.RR.perc <- bind_rows(plot3.male.meta.RR.perc, plot3.male.meta.RR.perc.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
# **Re-structure data for each grouping term; delete un-used variables: "Hearing missing for all 3 parameters"

plot3.male.meta.CVR.perc.b <- as.data.frame(plot3.male.meta.CVR.perc %>% group_by(GroupingTerm) %>%
  mutate(
    lnCVR = map_dbl(model_lnCVR, pluck(2)), lnCVR_lower = map_dbl(model_lnCVR, pluck(6)),
    lnCVR_upper = map_dbl(model_lnCVR, pluck(7)), lnCVR_se = map_dbl(model_lnCVR, pluck(3))
  ))[, c(1, 4:7)]
add.row.hearing <- as.data.frame(t(c("Hearing", NA, NA, NA, NA))) %>% setNames(names(plot3.male.meta.CVR.perc.b))
plot3.male.meta.CVR.perc.b <- rbind(plot3.male.meta.CVR.perc.b, add.row.hearing)
plot3.male.meta.CVR.perc.b <- plot3.male.meta.CVR.perc.b[order(plot3.male.meta.CVR.perc.b$GroupingTerm), ]

plot3.male.meta.VR.perc.b <- as.data.frame(plot3.male.meta.VR.perc %>% group_by(GroupingTerm) %>%
  mutate(
    lnVR = map_dbl(model_lnVR, pluck(2)), lnVR_lower = map_dbl(model_lnVR, pluck(6)),
    lnVR_upper = map_dbl(model_lnVR, pluck(7)), lnVR_se = map_dbl(model_lnVR, pluck(3))
  ))[, c(1, 4:7)]
add.row.hearing <- as.data.frame(t(c("Hearing", NA, NA, NA, NA))) %>% setNames(names(plot3.male.meta.VR.perc.b))
plot3.male.meta.VR.perc.b <- rbind(plot3.male.meta.VR.perc.b, add.row.hearing)
plot3.male.meta.VR.perc.b <- plot3.male.meta.VR.perc.b[order(plot3.male.meta.VR.perc.b$GroupingTerm), ]

plot3.male.meta.RR.perc.b <- as.data.frame(plot3.male.meta.RR.perc %>% group_by(GroupingTerm) %>%
  mutate(
    lnRR = map_dbl(model_lnRR, pluck(2)), lnRR_lower = map_dbl(model_lnRR, pluck(6)),
    lnRR_upper = map_dbl(model_lnRR, pluck(7)), lnRR_se = map_dbl(model_lnRR, pluck(3))
  ))[, c(1, 4:7)]
add.row.hearing <- as.data.frame(t(c("Hearing", NA, NA, NA, NA))) %>%
  setNames(names(plot3.male.meta.RR.perc.b))
plot3.male.meta.RR.perc.b <- rbind(plot3.male.meta.RR.perc.b, add.row.hearing)

add.row.eye <- as.data.frame(t(c("Eye", NA, NA, NA, NA))) %>%
  setNames(names(plot3.male.meta.RR.perc.b))
plot3.male.meta.RR.perc.b <- rbind(plot3.male.meta.RR.perc.b, add.row.eye)

plot3.male.meta.RR.perc.b <- plot3.male.meta.RR.perc.b[order(plot3.male.meta.RR.perc.b$GroupingTerm), ]

plot3.male.meta.CVR.Vr.perc <- full_join(plot3.male.meta.CVR.perc.b, plot3.male.meta.VR.perc.b)
Joining, by = "GroupingTerm"
overall.male.plot3.perc <- full_join(plot3.male.meta.CVR.Vr.perc, plot3.male.meta.RR.perc.b)
Joining, by = "GroupingTerm"
overall.male.plot3.perc$GroupingTerm <- factor(overall.male.plot3.perc$GroupingTerm, levels = c("Behaviour", "Morphology", "Metabolism", "Physiology", "Immunology", "Hematology", "Heart", "Hearing", "Eye", "All"))
overall.male.plot3.perc$GroupingTerm <- factor(overall.male.plot3.perc$GroupingTerm, rev(levels(overall.male.plot3.perc$GroupingTerm)))

Restructure data for plotting : Male biased, 10% difference

overall3.perc <- gather(overall.male.plot3.perc, parameter, value, c(lnCVR, lnVR, lnRR), factor_key = TRUE) 

lnCVR.ci <- overall3.perc %>%
  filter(parameter == "lnCVR") %>%
  mutate(ci.low = lnCVR_lower, ci.high = lnCVR_upper)
lnVR.ci <- overall3.perc  %>% filter(parameter == "lnVR") %>% mutate(ci.low = lnVR_lower, ci.high = lnVR_upper)
lnRR.ci <- overall3.perc %>%
  filter(parameter == "lnRR") %>%
  mutate(ci.low = lnRR_lower, ci.high = lnRR_upper)

overall4.male.perc <- bind_rows(lnCVR.ci,lnVR.ci, lnRR.ci) %>% select(GroupingTerm, parameter, value, ci.low, ci.high) 

overall4.male.perc$label <- "Sex difference in m/f ratios > 10%"

overall4.male.perc$value <- as.numeric(overall4.male.perc$value)
overall4.male.perc$ci.low <- as.numeric(overall4.male.perc$ci.low)
overall4.male.perc$ci.high <- as.numeric(overall4.male.perc$ci.high)

Plot Fig S2 all >10% difference (male bias)

Female Fig S2 >10%


meta.plot3.perc <- metacombo %>%
  mutate(
    percCVR = ifelse(lnCVR < log(9 / 10), 1, 0),
    percVR = ifelse(lnVR < log(9 / 10), 1, 0),
    percRR = ifelse(lnRR < log(9 / 10), 1, 0)
  )

# Significant subset for lnCVR
metacombo_plot3.CVR.perc <- meta.plot3.perc %>%
  filter(percCVR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_plot3.CVR.perc.all <- meta.plot3.perc %>%
  filter(percCVR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# Significant subset for lnVR
metacombo_plot3.VR.perc <- meta.plot3.perc %>%
  filter(percVR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_plot3.VR.perc.all <- meta.plot3.perc %>%
  filter(percVR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# Significant subset for lnRR
metacombo_plot3.RR.perc <- meta.plot3.perc %>%
  filter(percRR == 1) %>%
  group_by(GroupingTerm) %>%
  nest()

metacombo_plot3.RR.perc.all <- meta.plot3.perc %>%
  filter(percRR == 1) %>%
  nest()
`...` must not be empty for ungrouped data frames.
Did you want `data = everything()`?
# **Final fixed effects meta-analyses within grouping terms, with SE of the estimate

plot3.meta.CVR.perc <- metacombo_plot3.CVR.perc %>%
  mutate(model_lnCVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnCVR, sei = (.x$lnCVR_upper - .x$lnCVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.meta.VR.perc <- metacombo_plot3.VR.perc %>%
  mutate(model_lnVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnVR, sei = (.x$lnVR_upper - .x$lnVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.meta.RR.perc <- metacombo_plot3.RR.perc %>%
  mutate(model_lnRR = map(data, ~ metafor::rma.uni(
    yi = .x$lnRR, sei = (.x$lnRR_upper - .x$lnRR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

# Across all grouping terms #

plot3.meta.CVR.perc.all <- metacombo_plot3.CVR.perc.all %>%
  mutate(model_lnCVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnCVR, sei = (.x$lnCVR_upper - .x$lnCVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.meta.CVR.perc.all <- plot3.meta.CVR.perc.all %>% mutate(GroupingTerm = "All")

plot3.meta.VR.perc.all <- metacombo_plot3.VR.perc.all %>%
  mutate(model_lnVR = map(data, ~ metafor::rma.uni(
    yi = .x$lnVR, sei = (.x$lnVR_upper - .x$lnVR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.meta.VR.perc.all <- plot3.meta.VR.perc.all %>% mutate(GroupingTerm = "All")

plot3.meta.RR.perc.all <- metacombo_plot3.RR.perc.all %>%
  mutate(model_lnRR = map(data, ~ metafor::rma.uni(
    yi = .x$lnRR, sei = (.x$lnRR_upper - .x$lnRR_lower) / (2 * 1.96),
    control = list(optimizer = "optim", optmethod = "Nelder-Mead", maxit = 1000), verbose = F
  )))

plot3.meta.RR.perc.all <- plot3.meta.RR.perc.all %>% mutate(GroupingTerm = "All")

# Combine with separate grouping term results

plot3.meta.CVR.perc <- bind_rows(plot3.meta.CVR.perc, plot3.meta.CVR.perc.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
plot3.meta.VR.perc <- bind_rows(plot3.meta.VR.perc, plot3.meta.VR.perc.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
plot3.meta.RR.perc <- bind_rows(plot3.meta.RR.perc, plot3.meta.RR.perc.all)
Vectorizing 'vctrs_list_of' elements may not preserve their attributesVectorizing 'vctrs_list_of' elements may not preserve their attributes
# **Re-structure data for each grouping term; delete un-used variables: "Hearing missing for all 3 parameters"

plot3.meta.CVR.perc.b <- as.data.frame(plot3.meta.CVR.perc %>% group_by(GroupingTerm) %>%
  mutate(
    lnCVR = map_dbl(model_lnCVR, pluck(2)), lnCVR_lower = map_dbl(model_lnCVR, pluck(6)),
    lnCVR_upper = map_dbl(model_lnCVR, pluck(7)), lnCVR_se = map_dbl(model_lnCVR, pluck(3))
  ))[, c(1, 4:7)]
add.row.hearing <- as.data.frame(t(c("Hearing", NA, NA, NA, NA))) %>% setNames(names(plot3.meta.CVR.perc.b))
plot3.meta.CVR.perc.b <- rbind(plot3.meta.CVR.perc.b, add.row.hearing)
plot3.meta.CVR.perc.b <- plot3.meta.CVR.perc.b[order(plot3.meta.CVR.perc.b$GroupingTerm), ]

plot3.meta.VR.perc.b <- as.data.frame(plot3.meta.VR.perc %>% group_by(GroupingTerm) %>%
  mutate(
    lnVR = map_dbl(model_lnVR, pluck(2)), lnVR_lower = map_dbl(model_lnVR, pluck(6)),
    lnVR_upper = map_dbl(model_lnVR, pluck(7)), lnVR_se = map_dbl(model_lnVR, pluck(3))
  ))[, c(1, 4:7)]
add.row.hearing <- as.data.frame(t(c("Hearing", NA, NA, NA, NA))) %>% setNames(names(plot3.meta.VR.perc.b))
plot3.meta.VR.perc.b <- rbind(plot3.meta.VR.perc.b, add.row.hearing)
plot3.meta.VR.perc.b <- plot3.meta.VR.perc.b[order(plot3.meta.VR.perc.b$GroupingTerm), ]

plot3.meta.RR.perc.b <- as.data.frame(plot3.meta.RR.perc %>% group_by(GroupingTerm) %>%
  mutate(
    lnRR = map_dbl(model_lnRR, pluck(2)), lnRR_lower = map_dbl(model_lnRR, pluck(6)),
    lnRR_upper = map_dbl(model_lnRR, pluck(7)), lnRR_se = map_dbl(model_lnRR, pluck(3))
  ))[, c(1, 4:7)]
add.row.hearing <- as.data.frame(t(c("Hearing", NA, NA, NA, NA))) %>% setNames(names(plot3.meta.RR.perc.b))
plot3.meta.RR.perc.b <- rbind(plot3.meta.RR.perc.b, add.row.hearing)
add.row.hematology <- as.data.frame(t(c("Hematology", NA, NA, NA, NA))) %>%
  setNames(names(plot3.meta.RR.perc.b))
plot3.meta.RR.perc.b <- rbind(plot3.meta.RR.perc.b, add.row.hematology)


plot3.meta.RR.perc.b <- plot3.meta.RR.perc.b[order(plot3.meta.RR.perc.b$GroupingTerm), ]

plot3.meta.CVR.perc.c <- full_join(plot3.meta.CVR.perc.b, plot3.meta.VR.perc.b)
Joining, by = "GroupingTerm"
overall.plot3.perc <- full_join(plot3.meta.CVR.perc.c, plot3.meta.RR.perc.b)
Joining, by = "GroupingTerm"
overall.plot3.perc$GroupingTerm <- factor(overall.plot3.perc$GroupingTerm, levels = c("Behaviour", "Morphology", "Metabolism", "Physiology", "Immunology", "Hematology", "Heart", "Hearing", "Eye", "All"))
overall.plot3.perc$GroupingTerm <- factor(overall.plot3.perc$GroupingTerm, rev(levels(overall.plot3.perc$GroupingTerm)))

Restructure data for plotting Female bias, 10 percent difference

overall3.perc <- gather(overall.plot3.perc, parameter, value, c(lnCVR, lnVR, lnRR), factor_key = TRUE) 

lnCVR.ci <- overall3.perc %>%
  filter(parameter == "lnCVR") %>%
  mutate(ci.low = lnCVR_lower, ci.high = lnCVR_upper)
lnVR.ci <- overall3.perc  %>% filter(parameter == "lnVR") %>% mutate(ci.low = lnVR_lower, ci.high = lnVR_upper)
lnRR.ci <- overall3.perc %>%
  filter(parameter == "lnRR") %>%
  mutate(ci.low = lnRR_lower, ci.high = lnRR_upper)

overall4.perc <- bind_rows(lnCVR.ci, lnVR.ci, lnRR.ci) %>% select(GroupingTerm, parameter, value, ci.low, ci.high)

overall4.perc$label <- "Sex difference in m/f ratios > 10%"

overall4.perc$value <- as.numeric(overall4.perc$value)
overall4.perc$ci.low <- as.numeric(overall4.perc$ci.low)
overall4.perc$ci.high <- as.numeric(overall4.perc$ci.high)

Plot FigS2 all >10% difference (female)

Plot Fig S2: plots combined

library(ggpubr)
FigS2b <- ggarrange(Metameta_Fig3_female.sig, Metameta_Fig3_male.sig,
  ncol = 2, nrow = 1, widths = c(1, 1.20), heights = c(1, 1)
)
Removed 5 rows containing missing values (geom_errorbarh).Removed 4 rows containing missing values (geom_point).Removed 9 rows containing missing values (geom_errorbarh).Removed 9 rows containing missing values (geom_point).
FigS2d <- ggarrange(Metameta_Fig3_female.perc, Metameta_Fig3_male.perc,
  ncol = 2, nrow = 1, widths = c(1, 1.20), heights = c(1, 1)
)
Removed 9 rows containing missing values (geom_errorbarh).Removed 9 rows containing missing values (geom_point).Removed 7 rows containing missing values (geom_errorbarh).Removed 7 rows containing missing values (geom_point).
# end combination Figure 5
FigS2 <- ggarrange(malebias_FigS2_sigtraits, malebias_Fig2_over10, FigS2b, FigS2d, ncol = 1, nrow = 4, heights = c(2.3, 2, 2.1, 2), labels = c("A", " ", "B", " "))
Removed 2 rows containing missing values (position_stack).Removed 8 rows containing missing values (position_stack).
FigS2

NOT SURE WHAT THIS BELOW IS??

Figure S2: sex-bias, including VR

Prepare data for traits with effect size ratios > 10% larger in males

meta.plotS2.over10 <- meta_clean %>%
  select(lnCVR, lnVR, lnRR, GroupingTerm) %>%
  arrange(GroupingTerm)

meta.plotS2.over10.b <- gather(meta.plotS2.over10, trait, value, c(lnCVR, lnVR, lnRR))

meta.plotS2.over10.b$trait <- factor(meta.plotS2.over10.b$trait, levels = c("lnCVR", "lnVR", "lnRR"))

meta.plotS2.over10.c <- meta.plotS2.over10.b %>%
  group_by_at(vars(trait, GroupingTerm)) %>%
  summarise(
    malebias = sum(value > log(11 / 10)), femalebias = sum(value < log(9 / 10)), total = malebias + femalebias,
    malepercent = malebias * 100 / total, femalepercent = femalebias * 100 / total
  )

meta.plotS2.over10.c$label <- "Sex difference in m/f ratios > 10%"

# restructure to create stacked bar plots

meta.plotS2.over10.c <- as.data.frame(meta.plotS2.over10.c)
meta.plotS2.over10.d <- gather(meta.plotS2.over10.c, key = sex, value = percent, malepercent:femalepercent, factor_key = TRUE)

# create new sample size variable

meta.plotS2.over10.d$samplesize <- with(meta.plotS2.over10.d, ifelse(sex == "malepercent", malebias, femalebias))

# *Plot FigS2 Sex difference in m/f ratio > 10%
malebias_FigS2_over10 <-
  ggplot(meta.plotS2.over10.d) +
  aes(x = GroupingTerm, y = percent, fill = sex) +
  geom_col() +
  geom_hline(yintercept = 50, linetype = "dashed", color = "gray40") +
  geom_text(
    data = subset(meta.plot2.over10.d, samplesize != 0), aes(label = samplesize), position = position_stack(vjust = .5),
    color = "white", size = 3.5
  ) +
  facet_grid(
    cols = vars(trait), rows = vars(label), labeller = label_wrap_gen(width = 18),
    scales = "free", space = "free"
  ) +
  scale_fill_brewer(palette = "Set2") +
  theme_bw(base_size = 18) +
  theme(
    strip.text.y = element_text(angle = 270, size = 10, margin = margin(t = 15, r = 15, b = 15, l = 15)),
    strip.text.x = element_blank(),
    strip.background = element_rect(colour = NULL, linetype = "blank", fill = "gray90"),
    text = element_text(size = 14),
    panel.spacing = unit(0.5, "lines"),
    panel.border = element_blank(),
    axis.line = element_line(),
    panel.grid.major.x = element_line(linetype = "solid", colour = "gray95"),
    panel.grid.major.y = element_line(linetype = "solid", color = "gray95"),
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank(),
    legend.position = "none",
    axis.title.x = element_blank(),
    axis.title.y = element_blank()
  ) +
  coord_flip()

# malebias_FigS2_over10  #(Panel B in Fig S2 in ms)

#Metameta_FigS2_male.sig (Figure 5B right panel)

Restructure MALE data for plotting

Plot FigS2 all significant results (CI not overlapping zero, male )

10 % Perc sex difference, male bias

Restructure data for plotting : Male biased, 10% difference

Plot FigS2 all >10% difference (male bias)

Restructure data for plotting: Female bias, 10 percent difference, including VR

Plot Fig5D all >10% difference (female)

Figure S2

Acknowledgements

tbd

R Session Information

LS0tCnRpdGxlOiAiSU1QQyBNb3VzZSBkYXRhIC0gVmFyaWFuY2UgaW4gc2V4IGRpZmZlcmVuY2VzIgphdXRob3I6ICJTdXNhbm5lIFphaml0c2NoZWssICBGZWxpeCBaYWppdHNjaGVrLCBSdXNzZWxsIEJvbmR1cmlhbnNreSxSb2JlcnQgIEJyb29rcywgV2lsbCBDb3Jud2VsbCwgRGFuaWVsIEZhbHN0ZXIsIE1hbGdvcnRhemEgTGFnaXN6LCBKZXJlbXkgTWFzb24sIERhbmllbCBOb2JsZSwgQWxpc3RhaXIgU2VuaW9yICYgU2hpbmljaGkgTmFrYWdhd2EiCmRhdGU6ICJBdWd1c3QgMjAxOSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGRlcHRoOiA0CiAgICBudW1iZXJfc2VjdGlvbnM6IG5vCiAgICB0aGVtZTogIGZsYXRseQogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNAogICAgdG9jX2Zsb2F0OiB5ZXMKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAnNCcKc3VidGl0bGU6IEVsZWN0cm9uaWMgU3VwcGxlbWVudGFyeSBNYXRlcmlhbAotLS0KCiMgU2V0LXVwCgojIyBMb2FkaW5nIHBhY2thZ2VzICYgY3VzdG9tIGZ1bmN0aW9ucwoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0gVFJVRSwKICB3YXJuaW5nID0gRkFMU0UsCiAgbWVzc2FnZSA9IEZBTFNFLAogIGNhY2hlID0gVFJVRSwKICB0aWR5ID0gVFJVRQopCmBgYAoKYGBge3J9CmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobWV0YWZvcikKbGlicmFyeShkZXZ0b29scykKbGlicmFyeShwdXJycikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkodGliYmxlKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkocm9idW1ldGEpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoaGVyZSkKYGBgCgpGdW5jdGlvbnMgZm9yIHByZXBhcmluZyB0aGUgZGF0YSBmb3IgbWV0YSBhbmFseXNlcwoKMSkgQ3JlYXRlIGZ1bmN0aW9uIGZvciBzdWItc2V0dGluZyB0aGUgZGF0YSB0byBjaG9vc2Ugb25seSBvbmUgZGF0YSBwb2ludCBwZXIgaW5kaXZpZHVhbCBwZXIgdHJhaXQ6ICJkYXRhX3N1YnNldF9wYXJhbWV0ZXJpZF9pbmRpdmlkdWFsX2J5X2FnZSIKCmBgYHtyfQpkYXRhX3N1YnNldF9wYXJhbWV0ZXJpZF9pbmRpdmlkdWFsX2J5X2FnZSA8LSBmdW5jdGlvbihteWRhdGEsIHBhcmFtZXRlciwgYWdlX21pbj0wLCBhZ2VfY2VudGVyPTEwMCkgewogIHRtcCA8LSBteWRhdGEgJT4lCiAgICBmaWx0ZXIoCiAgICAgIGFnZV9pbl9kYXlzID49IGFnZV9taW4sCiAgICAgIGlkID09IHBhcmFtZXRlcgogICAgKSAlPiUKICAgICMgdGFrZSByZXN1bHRzIGZvciBzaW5nbGUgaW5kaXZpZHVhbCBjbG9zZXN0IHRvIGFnZV9jZW50ZXIKICAgIG11dGF0ZShhZ2VfZGlmZiA9IGFicyhhZ2VfY2VudGVyIC0gYWdlX2luX2RheXMpKSAlPiUKICAgIGdyb3VwX2J5KGJpb2xvZ2ljYWxfc2FtcGxlX2lkKSAlPiUKICAgIGZpbHRlcihhZ2VfZGlmZiA9PSBtaW4oYWdlX2RpZmYpKSAlPiUKICAgIHNlbGVjdCgtYWdlX2RpZmYpIyAlPiUgCiMgICAgZmlsdGVyKCFkdXBsaWNhdGVkKGJpb2xvZ2ljYWxfc2FtcGxlX2lkKSkKICAgIAogICMgc3RpbGwgc29tZSBpbmRpdmlkdWFscyB3aXRoIG11bHRpcGxlIHJlY29yZHMgKGJlY2F1c2Ugc2FtZSBpbmRpdmlkdWFsIGFwcGVhciB1bmRlciBkaWZmZXJlbnQgcHJvY2VkdXJlcywgc28gZmlsdGVyIHRvIG9uZSByZWNvcmQpCiAgaiA8LSBtYXRjaCh1bmlxdWUodG1wJGJpb2xvZ2ljYWxfc2FtcGxlX2lkKSwgdG1wJGJpb2xvZ2ljYWxfc2FtcGxlX2lkKQogIHRtcFtqLCBdIAogIH0KYGBgCgoyKSAiUG9wdWxhdGlvbiBzdGF0aXN0aWNzIjogImNhbGN1bGF0ZV9wb3B1bGF0aW9uX3N0YXRzIgpUaGlzIGZ1bmN0aW9uIGdyb3VwcyBhbmltYWxzIGZyb20gdGhlIHNhbWUgc3RyYWluIGFuZCBzYW1lIGluc2l0aXV0aW9uIHRvZ2V0aGVyLiBUaGlzIGlzIGRvbmUgZm9yIGVhY2ggdHJhaXQgc2VvYXJhdGVseSwgYW5kIG9ubHkgZm9yIHRyYWl0cyB0aGF0IGhhdmUgYmVlbiBtZWFzdXJlZCBpbiBib3RoIHNleGVzLiBBbnkgZ3JvdXAgY29udGFpbmluZyBmZXdlciB0aGFuIDUgaW5kaXZpZHVhbHMgaXMgZXhjbHVkZWQuCgpgYGB7cn0KY2FsY3VsYXRlX3BvcHVsYXRpb25fc3RhdHMgPC0gZnVuY3Rpb24obXlkYXRhLCBtaW5faW5kaXZpZHVhbHMgPSA1KSB7CiAgbXlkYXRhICU+JQogICAgZ3JvdXBfYnkocG9wdWxhdGlvbiwgc3RyYWluX25hbWUsIHByb2R1Y3Rpb25fY2VudGVyLCBzZXgpICU+JQogICAgc3VtbWFyaXNlKAogICAgICB0cmFpdCA9IHBhcmFtZXRlcl9uYW1lWzFdLAogICAgICB4X2JhciA9IG1lYW4oZGF0YV9wb2ludCksCiAgICAgIHhfc2QgPSBzZChkYXRhX3BvaW50KSwKICAgICAgbl9pbmQgPSBuKCkKICAgICkgJT4lCiAgICB1bmdyb3VwKCkgJT4lCiAgICBmaWx0ZXIobl9pbmQgPiBtaW5faW5kaXZpZHVhbHMpICU+JQogICAgIyBDaGVjayBib3RoIHNleGVzIHByZXNlbnQgJiBmaWx0ZXIgdGhvc2UgbWlzc2luZwogICAgZ3JvdXBfYnkocG9wdWxhdGlvbikgJT4lCiAgICBtdXRhdGUoCiAgICAgIG5fc2V4ID0gbl9kaXN0aW5jdChzZXgpCiAgICApICU+JQogICAgdW5ncm91cCgpICU+JQogICAgZmlsdGVyKG5fc2V4ID09IDIpICU+JQogICAgc2VsZWN0KC1uX3NleCkgJT4lCiAgICBhcnJhbmdlKHByb2R1Y3Rpb25fY2VudGVyLCBzdHJhaW5fbmFtZSwgcG9wdWxhdGlvbiwgc2V4KQp9CmBgYAoKMykgRXh0cmFjdGlvbiBvZiBlZmZlY3Qgc2l6ZXMgYW5kIHNhbXBsZSB2YXJpYW5jZXM6ICJjcmVhdGVfbWV0YV9hbmFseXNpc19lZmZlY3Rfc2l6ZXMiCgpgYGB7cn0KY3JlYXRlX21ldGFfYW5hbHlzaXNfZWZmZWN0X3NpemVzIDwtIGZ1bmN0aW9uKG15ZGF0YSkgewogIGkgPC0gc2VxKDEsIG5yb3cobXlkYXRhKSwgYnkgPSAyKQogIGlucHV0IDwtIGRhdGEuZnJhbWUoCiAgICBuMWkgPSBteWRhdGEkbl9pbmRbaV0sCiAgICBuMmkgPSBteWRhdGEkbl9pbmRbaSArIDFdLAogICAgeDFpID0gbXlkYXRhJHhfYmFyW2ldLAogICAgeDJpID0gbXlkYXRhJHhfYmFyW2kgKyAxXSwKICAgIHNkMWkgPSBteWRhdGEkeF9zZFtpXSwKICAgIHNkMmkgPSBteWRhdGEkeF9zZFtpICsgMV0KICApCgogIG15ZGF0YVtpLCBdICU+JQogICAgc2VsZWN0KHN0cmFpbl9uYW1lLCBwcm9kdWN0aW9uX2NlbnRlciwgdHJhaXQpICU+JQogICAgbXV0YXRlKAogICAgICBlZmZlY3Rfc2l6ZV9DVlIgPSBjYWxjdWxhdGVfbG5DVlIoQ01lYW4gPSBpbnB1dCR4MWksIENTRCA9IGlucHV0JHNkMWksIENOID0gaW5wdXQkbjFpLCBFTWVhbiA9IGlucHV0JHgyaSwgRVNEID0gaW5wdXQkc2QyaSwgRU4gPSBpbnB1dCRuMmkpLAogICAgICBzYW1wbGVfdmFyaWFuY2VfQ1ZSID0gY2FsY3VsYXRlX3Zhcl9sbkNWUihDTWVhbiA9IGlucHV0JHgxaSwgQ1NEID0gaW5wdXQkc2QxaSwgQ04gPSBpbnB1dCRuMWksIEVNZWFuID0gaW5wdXQkeDJpLCBFU0QgPSBpbnB1dCRzZDJpLCBFTiA9IGlucHV0JG4yaSksCiAgICAgIGVmZmVjdF9zaXplX1ZSID0gY2FsY3VsYXRlX2xuVlIoQ1NEID0gaW5wdXQkc2QxaSwgQ04gPSBpbnB1dCRuMWksIEVTRCA9IGlucHV0JHNkMmksIEVOID0gaW5wdXQkbjJpKSwKICAgICAgc2FtcGxlX3ZhcmlhbmNlX1ZSID0gY2FsY3VsYXRlX3Zhcl9sblZSKENOID0gaW5wdXQkbjFpLCBFTiA9IGlucHV0JG4yaSksCiAgICAgIGVmZmVjdF9zaXplX1JSID0gY2FsY3VsYXRlX2xuUlIoQ01lYW4gPSBpbnB1dCR4MWksIENTRCA9IGlucHV0JHNkMWksIENOID0gaW5wdXQkbjFpLCBFTWVhbiA9IGlucHV0JHgyaSwgRVNEID0gaW5wdXQkc2QyaSwgRU4gPSBpbnB1dCRuMmkpLAogICAgICBzYW1wbGVfdmFyaWFuY2VfUlIgPSBjYWxjdWxhdGVfdmFyX2xuUlIoQ01lYW4gPSBpbnB1dCR4MWksIENTRCA9IGlucHV0JHNkMWksIENOID0gaW5wdXQkbjFpLCBFTWVhbiA9IGlucHV0JHgyaSwgRVNEID0gaW5wdXQkc2QyaSwgRU4gPSBpbnB1dCRuMmkpLAogICAgICBlcnIgPSBhcy5mYWN0b3Ioc2VxX2xlbihuKCkpKQogICAgKQp9CmBgYAoKIAo0KSBDYWxjdWxhdGUgbWV0YS1hbmFseXNpcyBzdGF0aXN0aWNzCgpCYXNlZCBvbiBmdW5jdGlvbiBjcmVhdGVkIGJ5IEEgTSBTZW5pb3IgQCB0aGUgVW5pdmVyc2l0eSBvZiBPdGFnbyBOWiAwMy8wMS8yMDE0OiAKCiogQ2FsY3VsYXRlcyBlZmZlY3Qgc2l6ZXMgZm9yIG1ldGEtYW5hbHlzaXMgb2YgdmFyaWFuY2UuICBBbGwgZnVuY3Rpb25zIHRha2UgdGhlIG1lYW4sIHNkIGFuZCBuIGZyb20gdGhlIGNvbnRyb2wgYW5kIGV4cGVyaW1lbnRhbCBncm91cHMuCiogVGhlIGZpcnN0IGZ1bmN0aW9uLCBjYWxjdWxhdGVfbG5DVlIsIGNhbGN1bGF0ZXMgdGhlIHRoZSBsb2cgcmVzcG9uc2UtcmF0aW8gb2YgdGhlIGNvZWZmaWNpZW50IG9mIHZhcmlhbmNlIChsbkNWUikgLSBzZWUgTmFrYWdhd2EgZXQgYWwgMjAxNS4KKiBUaGUgc2Vjb25kIGZ1bmN0aW9uIGNhbGN1bGF0ZXMgdGhlIG1lYXN1cmVtZW50IGVycm9yIHZhcmlhbmNlIGZvciBsbkNWUi4gQXMgd2VsbCBhcyB0aGUgYWZvcmVtZW50aW9uZWQgcGFyYW1ldGVycywgdGhpcyBmdW5jdGlvbiBhbHNvIHRha2VzIEVxdWFsX0VfQ19Db3JyIChkZWZhdWx0ID0gVCksIHdoaWNoIG11c3QgYmUgVHJ1ZSBvciBGYWxzZS4gSWYgdHJ1ZSwgdGhlIGZ1bmN0aW9uIGFzc3VtZXMgdGhhdCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBtZWFuIGFuZCBzZCAoVGF5bG9yJ3MgTGF3KSAgaXMgZXF1YWwgZm9yIHRoZSBtZWFuIGFuZCBjb250cm9sIGdyb3VwcywgYW5kLCB0aHVzIHRoZXNlIGRhdGEgYXJlIHBvb2xlZC4gSWYgRmFsc2UgdGhlIG1lYW4tU0QgY29ycmVsYXRpb24gZm9yIHRoZSBleHBlcmltZW50YWwgYW5kIGNvbnRyb2wgZ3JvdXBzIGFyZSBjYWxjdWxhdGVkIHNlcGFyYXRlbHkgZnJvbSBvbmUgYW5vdGhlci4KKiBTaW1pbGFyIGZ1bmN0aW9ucyBhcmUgdGhlbiBpbXBsZW1lbnRlZCBmb3IgbG5WUiAoZm9yIGNvbXBhcmlzb24gb2Ygc3RhbmRhcmQgZGV2aWF0aW9ucykgYW5kIGxuIFJSICAoZm9yIGNvbXBhcmlzb24gb2YgbWVhbnMpIAogCmBgYHtyfQoKY2FsY3VsYXRlX2xuQ1ZSIDwtIGZ1bmN0aW9uKENNZWFuLCBDU0QsIENOLCBFTWVhbiwgRVNELCBFTikgewogIGxvZyhFU0QpIC0gbG9nKEVNZWFuKSArIDEgLyAoMiAqIChFTiAtIDEpKSAtIChsb2coQ1NEKSAtIGxvZyhDTWVhbikgKyAxIC8gKDIgKiAoQ04gLSAxKSkpCn0KCmNhbGN1bGF0ZV92YXJfbG5DVlIgPC0gZnVuY3Rpb24oQ01lYW4sIENTRCwgQ04sIEVNZWFuLCBFU0QsIEVOLCBFcXVhbF9FX0NfQ29yciA9IFQpIHsKICBpZiAoRXF1YWxfRV9DX0NvcnIgPT0gVCkgewogICAgbXZjb3JyIDwtIDAgIyBjb3IudGVzdChsb2coYyhDTWVhbiwgRU1lYW4pKSwgbG9nKGMoQ1NELCBFU0QpKSkkZXN0aW1hdGUgICBvbGQsIHNsaWdodGx5IGluY29ycmVjdAogICAgUzIgPC0gQ1NEXjIgLyAoQ04gKiAoQ01lYW5eMikpICsgMSAvICgyICogKENOIC0gMSkpIC0gMiAqIG12Y29yciAqIHNxcnQoKENTRF4yIC8gKENOICogKENNZWFuXjIpKSkgKiAoMSAvICgyICogKENOIC0gMSkpKSkgKyBFU0ReMiAvIChFTiAqIChFTWVhbl4yKSkgKyAxIC8gKDIgKiAoRU4gLSAxKSkgLSAyICogbXZjb3JyICogc3FydCgoRVNEXjIgLyAoRU4gKiAoRU1lYW5eMikpKSAqICgxIC8gKDIgKiAoRU4gLSAxKSkpKQogIH0KICBlbHNlIHsKICAgIENtdmNvcnIgPC0gY29yLnRlc3QobG9nKENNZWFuKSwgbG9nKENTRCkpJGVzdGltYXRlCiAgICBFbXZjb3JyIDwtIGNvci50ZXN0KGxvZyhFTWVhbiksIChFU0QpKSRlc3RpbWF0ZQogICAgUzIgPC0gQ1NEXjIgLyAoQ04gKiAoQ01lYW5eMikpICsgMSAvICgyICogKENOIC0gMSkpIC0gMiAqIENtdmNvcnIgKiBzcXJ0KChDU0ReMiAvIChDTiAqIChDTWVhbl4yKSkpICogKDEgLyAoMiAqIChDTiAtIDEpKSkpICsgRVNEXjIgLyAoRU4gKiAoRU1lYW5eMikpICsgMSAvICgyICogKEVOIC0gMSkpIC0gMiAqIEVtdmNvcnIgKiBzcXJ0KChFU0ReMiAvIChFTiAqIChFTWVhbl4yKSkpICogKDEgLyAoMiAqIChFTiAtIDEpKSkpCiAgfQogIFMyCn0KCmNhbGN1bGF0ZV9sblZSIDwtIGZ1bmN0aW9uKENTRCwgQ04sIEVTRCwgRU4pIHsKICBsb2coRVNEKSAtIGxvZyhDU0QpICsgMSAvICgyICogKEVOIC0gMSkpIC0gMSAvICgyICogKENOIC0gMSkpCn0KCmNhbGN1bGF0ZV92YXJfbG5WUiA8LSBmdW5jdGlvbihDTiwgRU4pIHsKICAxIC8gKDIgKiAoRU4gLSAxKSkgKyAxIC8gKDIgKiAoQ04gLSAxKSkKfQoKY2FsY3VsYXRlX2xuUlIgPC0gZnVuY3Rpb24oQ01lYW4sIENTRCwgQ04sIEVNZWFuLCBFU0QsIEVOKSB7CiAgbG9nKEVNZWFuKSAtIGxvZyhDTWVhbikKfQoKY2FsY3VsYXRlX3Zhcl9sblJSIDwtIGZ1bmN0aW9uKENNZWFuLCBDU0QsIENOLCBFTWVhbiwgRVNELCBFTikgewogIENTRF4yIC8gKENOICogQ01lYW5eMikgKyBFU0ReMiAvIChFTiAqIEVNZWFuXjIpCn0KYGBgCgojIyBMb2FkICYgY2xlYW4gZGF0YQoKMSkgRGF0YSBsb2FkaW5nIGFuZCBjbGVhbmluZyBvZiB0aGUgY3N2IGZpbGUKClRoaXMgc3RlcCB3ZSBoYXZlIGFscmVhZHkgZG9uZSBhbmQgcHJvdmlkZSBhIGNsZWFuZWQgdXAgZmlsZSB3aGljaCBpcyBsZXNzIGNvbXB1dGluZyBpbnRlbnNpdmUgYW5kIHdoaWNoIHdlIGhhdmUgc2F2ZWQgaW4gYSBmb2xkZXIgY2FsbGVkIGBleHBvcnRgLiBIb3dldmVyLCB0aGUgY3ZzIGlzIHByb3ZpZGVkIGluIGNhc2UgdGhpcyBpcyBwcmVmZXJyZWQgdG8gYmUgYXR0ZW1wdGVkLCBmb2xsb3dpbmcgdGhlIHN0ZXBzIGJlbG93OgoKYGBge3IgY2xlYW4sIGV2YWw9RkFMU0UsIGluY2x1ZGU9VFJVRX0KIyBsb2FkcyB0aGUgcmF3IGRhdGEsIHNldHRpbmcgc29tZSBkZWZhdWx0IHR5cGVzIGZvciB2YXJpb3VzIGNvbHVtbnMKCmxvYWRfcmF3IDwtIGZ1bmN0aW9uKGZpbGVuYW1lKSB7CiAgcmVhZF9jc3YoZmlsZW5hbWUsCiAgICBjb2xfdHlwZXMgPSBjb2xzKAogICAgICAuZGVmYXVsdCA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgcHJvamVjdF9pZCA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgaWQgPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgIHBhcmFtZXRlcl9pZCA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgYWdlX2luX2RheXMgPSBjb2xfaW50ZWdlcigpLAogICAgICBkYXRlX29mX2V4cGVyaW1lbnQgPSBjb2xfZGF0ZXRpbWUoZm9ybWF0ID0gIiIpLAogICAgICB3ZWlnaHQgPSBjb2xfZG91YmxlKCksCiAgICAgIHBoZW5vdHlwaW5nX2NlbnRlcl9pZCA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgcHJvZHVjdGlvbl9jZW50ZXJfaWQgPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgIHdlaWdodF9kYXRlID0gY29sX2RhdGV0aW1lKGZvcm1hdCA9ICIiKSwKICAgICAgZGF0ZV9vZl9iaXJ0aCA9IGNvbF9kYXRldGltZShmb3JtYXQgPSAiIiksCiAgICAgIHByb2NlZHVyZV9pZCA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgcGlwZWxpbmVfaWQgPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgIGJpb2xvZ2ljYWxfc2FtcGxlX2lkID0gY29sX2NoYXJhY3RlcigpLAogICAgICBiaW9sb2dpY2FsX21vZGVsX2lkID0gY29sX2NoYXJhY3RlcigpLAogICAgICB3ZWlnaHRfZGF5c19vbGQgPSBjb2xfaW50ZWdlcigpLAogICAgICBkYXRhc291cmNlX2lkID0gY29sX2NoYXJhY3RlcigpLAogICAgICBleHBlcmltZW50X2lkID0gY29sX2NoYXJhY3RlcigpLAogICAgICBkYXRhX3BvaW50ID0gY29sX2RvdWJsZSgpLAogICAgICBhZ2VfaW5fd2Vla3MgPSBjb2xfaW50ZWdlcigpLAogICAgICBgX3ZlcnNpb25fYCA9IGNvbF9jaGFyYWN0ZXIoKQogICAgKQogICkKfQoKIyBBcHBseSBzb21lIHN0YW5kYXJkIGNsZWFuaW5nIHRvIHRoZSBkYXRhCmNsZWFuX3Jhd19kYXRhIDwtIGZ1bmN0aW9uKG15ZGF0YSkgewogIAogIGdyb3VwIDwtIHJlYWRfY3N2KGhlcmUoImRhdGEiLCAiUGFyYW1ldGVyR3JvdXBpbmcuY3N2IikpCiAgCiAgdG1wIDwtIAogICAgbXlkYXRhICU+JQoKICAgICMgRmlsdGVyIHRvIElNUEMgc291cmNlIChyZWNvbW1lbmQgYnkgSmVyZW1leSBpbiBlbWFpbCB0byBTdXNpIG9uIDIwIEF1ZyAyMDE4KQogICAgZmlsdGVyKGRhdGFzb3VyY2VfbmFtZSA9PSAiSU1QQyIpICU+JQoKICAgICMgc3RhbmRhcmRpc2UgdHJhaXQgbmFtZXMKICAgIG11dGF0ZShwYXJhbWV0ZXJfbmFtZSA9IHRvbG93ZXIocGFyYW1ldGVyX25hbWUpKSAlPiUKCiAgICAjIHJlbW92ZSBleHRyZW1lIGFnZXMKICAgIGZpbHRlcihhZ2VfaW5fZGF5cyA+IDAgJiBhZ2VfaW5fZGF5cyA8IDUwMCkgJT4lCgogICAgIyByZW1vdmUgTkFzCiAgICBmaWx0ZXIoIWlzLm5hKGRhdGFfcG9pbnQpKSAlPiUKCiAgICAjIHN1YnNldCB0byByZWFzb25hYmxlIHNldCBvZiB2YXJpYWJsZXMsIGRhdGVfb2ZfZXhwZXJpbWVudCB1c2VkIGFzIGFuIGluZGljYXRvciBvZiBiYXRjaC1sZXZlbCBlZmZlY3RzCiAgICBzZWxlY3QocHJvZHVjdGlvbl9jZW50ZXIsIHN0cmFpbl9uYW1lLCBzdHJhaW5fYWNjZXNzaW9uX2lkLCBiaW9sb2dpY2FsX3NhbXBsZV9pZCwgcGlwZWxpbmVfc3RhYmxlX2lkLCBwcm9jZWR1cmVfZ3JvdXAsIHByb2NlZHVyZV9uYW1lLCBzZXgsIGRhdGVfb2ZfZXhwZXJpbWVudCwgYWdlX2luX2RheXMsIHdlaWdodCwgcGFyYW1ldGVyX25hbWUsIGRhdGFfcG9pbnQpICU+JSAKCiAgICAjIHNvcnQKICAgIGFycmFuZ2UocHJvZHVjdGlvbl9jZW50ZXIsIGJpb2xvZ2ljYWxfc2FtcGxlX2lkLCBhZ2VfaW5fZGF5cykKICAgICAgCiAgICAjIGZpbHRlciB0byBncm91cHMgd2l0aCA+IDEgY2VudHJlICAKICAgIG1lcmdlKHRtcCwgCiAgICAgICAgICB0bXAgJT4lIGdyb3VwX2J5KHBhcmFtZXRlcl9uYW1lKSAlPiUKICAgIHN1bW1hcmlzZShjZW50ZXJfcGVyX3RyYWl0ID0gbGVuZ3RoKHVuaXF1ZShwcm9kdWN0aW9uX2NlbnRlciwgbmEucm0gPSBUUlVFKSkpCiAgICAgICAgKSU+JQogICAgZmlsdGVyKGNlbnRlcl9wZXJfdHJhaXQgPj0gMikgJT4lIAoKICAgICMgRGVmaW5lIHBvcHVsYXRpb24gdmFyaWFibGUKICAgIG11dGF0ZShwb3B1bGF0aW9uID0gc3ByaW50ZigiJXMtJXMiLCBwcm9kdWN0aW9uX2NlbnRlciwgc3RyYWluX25hbWUpKSAlPiUgCgogICAgIyBhZGQgZ3JvdXBpbmcgdmFyaWFibGU6IHRoZXNlIHdlcmUgZGVjaWRlZCBiYXNlZCBvbiBmdW5jdGlvbmFsIGdyb3VwcyBhbmQgcHJvY2VkdXJlcyAKICAgIG11dGF0ZShwYXJhbWV0ZXJfZ3JvdXAgPSBncm91cCRwYXJhbWV0ZXJbbWF0Y2gocGFyYW1ldGVyX25hbWUsIGdyb3VwJHBhcmFtZXRlcl9uYW1lKV0gKSAlPiUKICAgIAogICAgIyBBc3NpZ24gdW5pcXVlIElEcyAocGVyIHRyYWl0KQogICAgIyBlYWNoIHVuaXF1ZSBwYXJhbWV0ZXJfbmFtZSAoPXRyYWl0LHVzZSB0cmFpdCB2YXJpYWJsZSkgZ2V0cyBhIHVuaXF1ZSBudW1iZXIgKCdpZCcpCgogICAgIyBXZSBhZGQgYSBuZXcgdmFyaWFibGUsIHdoZXJlIHJlZHVuZGFudCB0cmFpdHMgYXJlIGNvbWJpbmVkCiAgICAjW25vdGUgaG93ZXZlciwgYXQgdGhpcyBzdGFnZSB0aGUgZGF0YXNldCBzdGlsbCBjb250YWlucyBub25zZW5zaWNhbCB0cmFpdHMsIGkuZS4gdHJhaXRzIHRoYXQgbWF5IG5vdCBjb250YWluIGFueSBpbmZvcm1hdGlvbiBvbiB2YXJpYW5jZV0KICAgIG11dGF0ZShpZCA9IG1hdGNoKHBhcmFtZXRlcl9uYW1lLCB1bmlxdWUocGFyYW1ldGVyX25hbWUpKSkgJT4lIAogICAgYXNfdGliYmxlKCkKfQoKIyBMb2FkIHJhdyBkYXRhIC0gc2F2ZSBjbGVhbmVkIGRhdGFzZXQgYXMgUkRTIGZvciByZXVzZQpkYXRhX3JhdyA8LSBsb2FkX3JhdyhoZXJlKCJkYXRhIiwiZHI3LjBfYWxsX2NvbnRyb2xfZGF0YS5jc3YuZ3oiKSkKZGlyLmNyZWF0ZSgiZXhwb3J0IiwgRiwgRikKCmRhdGEgPC0gZGF0YV9yYXcgJT4lIAogIGNsZWFuX3Jhd19kYXRhKCkgCnNhdmVSRFMoZGF0YSwgImV4cG9ydC9kYXRhX2NsZWFuLnJkcyIpCmBgYAoKRm9yIGFuYWx5c2lzIHdlIGxvYWQgdGhlIFJEUyBjcmVhdGVkIGFib3ZlIGFuZCBvdGhlciBkYXRhc2V0czoKCmBgYHtyIGxvYWR9CmRhdGEgPC0gcmVhZFJEUyhoZXJlKCJleHBvcnQiLCAiZGF0YV9jbGVhbi5yZHMiKSkgCgpwcm9jZWR1cmVzIDwtIHJlYWRfY3N2KGhlcmUoImRhdGEiLCAicHJvY2VkdXJlcy5jc3YiKSkKCmBgYAoKCkNoZWNraW5nIGxlbmd0aCBvZiBkaWZmZXJlbnQgdmFyaWFibGVzIGFuZCBzYW1wbGUgc2l6ZXMuCgojIFRhYmxlIDE6ICAiU3RyYWlucyBhbmQgQ2VudGVyIFNhbXBsZSBTaXplcyIKVGhpcyB0YWJsZSBzdW1tYXJpc2VzIHRoZSBhdmFpbGFibGUgbnVtYmVycyBvZiBtYWxlIGFuZCBmZW1hbGUgbWljZSBmcm9tIGVhY2ggc3RyYWluIGFuZCBvcmlnaW5hdGluZyBpbnN0aXR1dGlvbi4KCmBgYHtyfQpsZW5ndGgodW5pcXVlKGRhdGEkcGFyYW1ldGVyX25hbWUpKSAjIDIzMiB0cmFpdHMKbGVuZ3RoKHVuaXF1ZShkYXRhJHBhcmFtZXRlcl9ncm91cCkpICMgMTYxIHBhcmFtZXRlciBncm91cHMKbGVuZ3RoKHVuaXF1ZShkYXRhJHByb2NlZHVyZV9uYW1lKSkgIyAyNiBwcm9jZWR1cmUgZ3JvdXBzCmxlbmd0aCh1bmlxdWUoZGF0YSRiaW9sb2dpY2FsX3NhbXBsZV9pZCkpICMgMjcxNDcgaW5kaXZpZGlhbCBtaWNlICAgCgojbnVtYmVyIG9mIG1hbGVzIGFuZCBmZW1hbGVzIHBlciBzdHJhaW4gcGVyIHByb2R1Y3Rpb24gY2VudGVyIAprYWJsZShjYmluZChkYXRhICU+JSBncm91cF9ieShwcm9kdWN0aW9uX2NlbnRlciwgc3RyYWluX25hbWUpICU+JSBjb3VudChiaW9sb2dpY2FsX3NhbXBsZV9pZCwgc2V4KSAlPiUgY291bnQoc2V4KSAlPiUgcHJpbnQobiA9IEluZikpKSAlPiUKICBrYWJsZV9zdHlsaW5nKCkgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICI2MCUiLCBoZWlnaHQgPSAiMjAwcHgiKQpgYGAKCiMgTWV0YS1hbmFseXNlcwojIyAxLiBQb3B1bGF0aW9uIGFzIGFuYWx5c2lzIHVuaXQgCihTdGVwIEMsIEZpZ3VyZSAzIGluIG1haW4gZG9jdW1lbnQpCgojIyMgTG9vcDogTWV0YS1hbmFseXNlcyBvbiBhbGwgdHJhaXRzCgoqIFRoZSBsb29wIGNvbWJpbmVzIHRoZSBmdW5jdGlvbnMgbWVudGlvbmVkIGFib3ZlIGFuZCBmaWxscyB0aGUgZGF0YSBtYXRyaXggd2l0aCByZXN1bHRzIGZyb20gb3VyIG1ldGEgYW5hbHlzaXMuIAoqIEVycm9yIG1lc3NhZ2VzIGluZGljYXRlIHRyYWl0cyB0aGF0IGVpdGhlciBkaWQgbm90IHJlYWNoIGNvbnZlcmdlbmNlLCBvciB0aGF0IGRpZCBub3QgcmV0dXJuIG1lYW5pbmdmdWwgcmVzdWx0cyBpbiB0aGUgbWV0YS1hbmFseXNpcywgZHVlIHRvIGFic2VuY2Ugb2YgdmFyaWFuY2UuIFRob3NlIHRyYWl0cyB3aWxsIGJlIHJlbW92ZWQgaW4gbGF0ZXIgc3RlcHMsIG91dGxpbmVkIGJlbG93LgoKYGBge3J9CgoobiA8LSBsZW5ndGgodW5pcXVlKGRhdGEkaWQpKSkKCiMgQ3JlYXRlIGRhdGFmcmFtZSB0byBzdG9yZSByZXN1bHRzCnJlc3VsdHNfYWxsdHJhaXRzX2dyb3VwaW5nIDwtIAogICAgdGliYmxlKGlkID0gMTpuLCBsbkNWUj0wLCBsbkNWUl9sb3dlcj0wLCBsbkNWUl91cHBlcj0wLCAKICAgICAgICAgICBsbkNWUl9zZT0wLCBsblZSPTAsIGxuVlJfbG93ZXI9MCwgbG5WUl91cHBlcj0wLCAKICAgICAgICAgICBsblZSX3NlPTAsIGxuUlI9MCwgbG5SUl9sb3dlcj0wLCBsblJSX3VwcGVyPTAsIGxuUlJfc2U9MCwgc2FtcGxlU2l6ZT0wLCB0cmFpdD0wKQoKZm9yICh0IGluIDE6bikgewogIHRyeUNhdGNoKAogICAgewogICAgICByZXN1bHRzIDwtIGRhdGEgJT4lIAogICAgICAgIGRhdGFfc3Vic2V0X3BhcmFtZXRlcmlkX2luZGl2aWR1YWxfYnlfYWdlKHQpICU+JQogICAgICAgIGNhbGN1bGF0ZV9wb3B1bGF0aW9uX3N0YXRzKCkgJT4lCiAgICAgICAgY3JlYXRlX21ldGFfYW5hbHlzaXNfZWZmZWN0X3NpemVzKCkKCiAgICAgICMgbG5DVlIsICBsb2cgcmVwc29uc2UtcmF0aW8gb2YgdGhlIGNvZWZmaWNpZW50IG9mIHZhcmlhbmNlCiAgICAgIGN2ciA8LSBtZXRhZm9yOjpybWEubXYoeWkgPSBlZmZlY3Rfc2l6ZV9DVlIsIFYgPSBzYW1wbGVfdmFyaWFuY2VfQ1ZSLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSBsaXN0KH4gMSB8IHN0cmFpbl9uYW1lLCB+IDEgfCBwcm9kdWN0aW9uX2NlbnRlciwgfiAxIHwgZXJyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYsIGRhdGEgPSByZXN1bHRzKQoKICAgICAgIyBsblZSLCBjb21wYXJpc29uIG9mIHN0YW5kYXJkIGRldmlhdGlvbnMKICAgICAgY3YgPC0gbWV0YWZvcjo6cm1hLm12KHlpID0gZWZmZWN0X3NpemVfVlIsIFYgPSBzYW1wbGVfdmFyaWFuY2VfVlIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSBsaXN0KH4gMSB8IHN0cmFpbl9uYW1lLCB+IDEgfCBwcm9kdWN0aW9uX2NlbnRlciwgfiAxIHwgZXJyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sID0gbGlzdChvcHRpbWl6ZXIgPSAib3B0aW0iLCBvcHRtZXRob2QgPSAiTmVsZGVyLU1lYWQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heGl0ID0gMTAwMCksIHZlcmJvc2UgPSBGLCBkYXRhID0gcmVzdWx0cykKCiAgICAgICMgZm9yIG1lYW5zLCBsblJSCiAgICAgIG1lYW5zIDwtIG1ldGFmb3I6OnJtYS5tdih5aSA9IGVmZmVjdF9zaXplX1JSLCBWID0gc2FtcGxlX3ZhcmlhbmNlX1JSLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IGxpc3QofiAxIHwgc3RyYWluX25hbWUsIH4gMSB8IHByb2R1Y3Rpb25fY2VudGVyLCB+IDEgfCBlcnIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wgPSBsaXN0KG9wdGltaXplciA9ICJvcHRpbSIsIG9wdG1ldGhvZCA9ICJOZWxkZXItTWVhZCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYsIGRhdGEgPSByZXN1bHRzKQogICAgICAKICAgICAgZiA8LSBmdW5jdGlvbih4KSB1bmxpc3QoeFtjKCJiIiwgImNpLmxiIiwgImNpLnViIiwgInNlIildKQoKICAgICAgcmVzdWx0c19hbGx0cmFpdHNfZ3JvdXBpbmdbdCwgMjoxNF0gPC0gYyhmKGN2ciksIGYoY3YpLCBmKG1lYW5zKSwgbWVhbnMkaykKICAgICAgcmVzdWx0c19hbGx0cmFpdHNfZ3JvdXBpbmdbdCwgMTVdIDwtIHVuaXF1ZShyZXN1bHRzJHRyYWl0KQogICAgfSwKICAgIGVycm9yID0gZnVuY3Rpb24oZSkgewogICAgICBjYXQoIkVSUk9SIDoiLCB0LCBjb25kaXRpb25NZXNzYWdlKGUpLCAiXG4iKQogICAgfQogICkKfQpgYGAKCkluIHRoZSBhYm92ZSBmdW5jdGlvbiwgd2UgdXNlICd0cnlDYXRjaCcgYW5kICdjb25kaXRpb25NZXNzYWdlJyB0byBwcmV2ZW50IHRoZSBsb29wIGZyb20gYWJvcnRpbmcgd2hlbiB0aGUgZmlyc3QgZXJyb3IgYXQgcm93IDg0IGlzIHByb2R1Y2VkLgpBcyBjb252ZXJnZW5jZSBpbiB0aGUgdHdvIGxpc3RlZCBub24tY29udmVyZ2luZyBjYXNlcyBjYW4ndCBiZSBhY2hpZXZlZCBieSBzZW5zaWJseSB0d2Vha2luZyAob3RoZXIgb3B0aW0gZXRjLiksIGFuZCB3ZSBvbmx5IGxlYXJuIGFib3V0IG5vbi1jb252ZXJnZW5jZSBpbiB0aGUgbG9vcCwgaXQgaXMgbm90IHBvc3NpYmxlIHRvIGV4Y2x1ZGUgdGhlIHRyYWl0cyAoTj0yKSBiZWZvcmVoYW5kLgpTaW1pbGFybHksIHRoZXJlIGFyZSA4IHRyYWl0cyB3aXRoIHZlcnkgbG93IHZhcmlhdGlvbiwgd2hpY2ggY2FuIG5vdCBiZSBleGNsdWRlZCBwcmlvciBydW5uaW5nIHRoZSBsb29wLgoKVGhlIHByb2R1Y2VkICJXYXJuaW5ncyIgaW5kaWNhdGUgY2FzZXMgd2hlcmUgdmFyaWFuY2UgY29tcG9uZW50cyBhcmUgc2V0IHRvIHplcm8gZHVyaW5nIGxpa2VsaWhvb2Qgb3B0aW1pemF0aW9uLgoKCiMjIyBNZXJnaW5nIGRhdGFzZXRzICYgcmVtb3ZhbCBvZiBub24tY29udmVyZ2VkIHRyYWl0cwoKUHJvY2VkdXJlIG5hbWVzLCBncm91cGluZyB2YXJpYWJsZXMgYW5kIHRyYWl0IG5hbWVzICgicGFyYW1ldGVyX25hbWVzIikgYXJlIG1lcmdlZCBiYWNrIHRvZ2V0aGVyIHdpdGggdGhlIHJlc3VsdHMgZnJvbSB0aGUgbWV0YWZvciBhbmFseXNpcyBhYm92ZS4KIAoKYGBge3J9CnJlc3VsdHNfYWxsdHJhaXRzX2dyb3VwaW5nMiA8LSAKICByZXN1bHRzX2FsbHRyYWl0c19ncm91cGluZyAlPiUgCiAgbGVmdF9qb2luKGJ5PSJpZCIsCiAgICAgICAgICAgICBkYXRhICU+JSBzZWxlY3QoaWQsIHBhcmFtZXRlcl9ncm91cCwgcHJvY2VkdXJlID0gcHJvY2VkdXJlX25hbWUsIHByb2NlZHVyZV9uYW1lLCBwYXJhbWV0ZXJfbmFtZSkgJT4lICAgIyBXZSBmaWx0ZXIgZHVwbGljYXRlZCBpZCdzIHRvIGdldCBvbmx5IG9uZSB1bmlxdWUgcm93IHBlciBpZCAoYW5kIHRoZXJlIGlzIG9uZSBpZCBwZXIgcGFyYW1ldGVyX25hbWUpCiAgICAgICAgICAgICAgZmlsdGVyKCFkdXBsaWNhdGVkKGlkKSkKICAgICAgICAgICAgKSAlPiUKICAjIEJlbG93IHdlIGFkZCAncHJvY2VkdXJlJyAoZnJvbSB0aGUgcHJldmlvdXNseSBsb2FkZWQgJ3Byb2NlZHVyZXMuY3N2JykgYXMgYSB2YXJpYWJsZQogIGxlZnRfam9pbihieT0icHJvY2VkdXJlIiwgCiAgICAgICAgICAgIHByb2NlZHVyZXMgJT4lIGRpc3RpbmN0KCkKICAgICAgICAgICAgKQogIAoKKG4gPC0gbGVuZ3RoKHVuaXF1ZShyZXN1bHRzX2FsbHRyYWl0c19ncm91cGluZzIkcGFyYW1ldGVyX25hbWUpKSkgIyAyMzIKYGBgCgojIyMgUmVtb3ZhbCBvZiB0cmFpdHMgCjE0IHRyYWl0cyBmcm9tIHRoZSBvcmlnaW5hbGx5IDIzMiB0aGF0IGhhZCBiZWVuIGluY2x1ZGVkIGFyZSByZW1vdmVkIGJlY2F1c2UgdGhleSBlaXRoZXIgZGlkIG5vdCBhY2hpZXZlIGNvbnZlcmdlbmNlIG9yIGFyZSBub25zZW5zaWNhbCBmb3IgYW5hbHlzaXMgb2YgdmFyaWFuY2UgKHN1Y2ggYXMgdHJhaXRzIHRoYXQgc2hvdyBubyB2YXJpYXRpb24sIHNlZSBsaXN0IGJlbG93KS4gCgpOb3QgY29udmVyZ2VkOiAiZHAgdCBjZWxscyIsICJtemIgKGNkMjEvMzUgaGlnaCkiCgpOb3QgZW5vdWdoIHZhcmlhdGlvbjogIm51bWJlciBvZiBjYXVkYWwgdmVydGVicmFlIiwgIm51bWJlciBvZiBjZXJ2aWNhbCB2ZXJ0ZWJyYWUiLCAibnVtYmVyIG9mIGRpZ2l0cyIsICJudW1iZXIgb2YgbHVtYmFyIHZlcnRlYnJhZSIsICJudW1iZXIgb2YgcGVsdmljIHZlcnRlYnJhZSIsICJudW1iZXIgb2YgcmlicyBsZWZ0IiwibnVtYmVyIG9mIHJpYnMgcmlnaHQiLCAibnVtYmVyIG9mIHNpZ25hbHMiLCAibnVtYmVyIG9mIHRob3JhY2ljIHZlcnRlYnJhZSIsICJ0b3RhbCBudW1iZXIgb2YgYWNxdWlyZWQgZXZlbnRzIGluIHBhbmVsIGEiLCJ0b3RhbCBudW1iZXIgb2YgYWNxdWlyZWQgZXZlbnRzIGluIHBhbmVsIGIiLCAid2hvbGUgYXJlbmEgcGVybWFuZW5jZSIuCgoKYGBge3J9CiMgV2UgZXhjbHVkZSAxNCBwYXJhbWV0ZXIgbmFtZXMgZm9yIHdoaWNoIG1ldGFmb3IgbW9kZWxzIGRpZG4ndCBjb252ZXJnZSAoImRwIHQgY2VsbHMiLCAibXpiIChjZDIxLzM1IGhpZ2gpIiksIGFuZCBvZiBwYXJhbWV0ZXJzIHRoYXQgZG9uJ3QgaGFyYm91ciBlbm91Z2ggdmFyaWF0aW9uCm1ldGFfY2xlYW4gPC0gcmVzdWx0c19hbGx0cmFpdHNfZ3JvdXBpbmcyICU+JSAKCSAgZmlsdGVyKCFwYXJhbWV0ZXJfbmFtZSAlaW4lIGMoImRwIHQgY2VsbHMiLCAibXpiIChjZDIxLzM1IGhpZ2gpIiwgIm51bWJlciBvZiBjYXVkYWwgdmVydGVicmFlIiwgCgkgICJudW1iZXIgb2YgY2VydmljYWwgdmVydGVicmFlIiwgIm51bWJlciBvZiBkaWdpdHMiLCAibnVtYmVyIG9mIGx1bWJhciB2ZXJ0ZWJyYWUiLCAibnVtYmVyIG9mIHBlbHZpYyB2ZXJ0ZWJyYWUiLCAibnVtYmVyIG9mIHJpYnMgbGVmdCIsICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAibnVtYmVyIG9mIHJpYnMgcmlnaHQiLCAibnVtYmVyIG9mIHNpZ25hbHMiLCAibnVtYmVyIG9mIHRob3JhY2ljIHZlcnRlYnJhZSIsICJ0b3RhbCBudW1iZXIgb2YgYWNxdWlyZWQgZXZlbnRzIGluIHBhbmVsIGEiLAogICAgICAgICJ0b3RhbCBudW1iZXIgb2YgYWNxdWlyZWQgZXZlbnRzIGluIHBhbmVsIGIiLCAid2hvbGUgYXJlbmEgcGVybWFuZW5jZSIpKQoKYGBgCgoKKipSZXZlaXcqKjogY2hlY2sgYWdhaW5zdCBvbGQgc2NyaXB0IC0tIGlkZW50aWNhbCwgcmVtb3ZlIG9uY2UgZml4ZWQgIwojRmVsaXg6IG5vdCBzdXJlCgpgYGB7ciwgZXZhbD1GQUxTRX0KbWV0YV9jbGVhbi50ZXN0IDwtIHJlYWRSRFMoaGVyZSgiZXhwb3J0IiwgIm1ldGFfY2xlYW4udGVzdC5yZHMiKSkgIAphbGwuZXF1YWwobWV0YV9jbGVhbiwgbWV0YV9jbGVhbi50ZXN0ICU+JSBtdXRhdGUoaWQ9YXMuaW50ZWdlcihpZCksIHBhcmFtZXRlcl9ncm91cCA9IGFzLmNoYXJhY3RlcihwYXJhbWV0ZXJfZ3JvdXApLCBHcm91cGluZ1Rlcm0gPSBhcy5jaGFyYWN0ZXIoR3JvdXBpbmdUZXJtKSkpCmBgYApbMV0gIlJvd3MgaW4geCBidXQgbm90IHk6IDE2MiwgMTYxLiBSb3dzIGluIHkgYnV0IG5vdCB4OiAxNjIsIDE2MS4gIgpOb3Qgc3VyZT8/CgojIyAyLiBNZXRhLWFuYWx5c2lzOiBjb25kZW5zaW5nIG5vbi1pbmRlcGVuZGVudCB0cmFpdHMgCihTdGVwIEYgaW4gRmlndXJlIDMgaW4gbWFpbiBhcnRpY2xlKQoKIyMjIERlYWxpbmcgd2l0aCBDb3JyZWxhdGVkIFBhcmFtZXRlcnMsIHByZXBhcmF0aW9uCgpUaGlzIGRhdGFzZXQgY29udGFpbmVkIGEgbnVtYmVyIG9mIGhpZ2hseSBjb3JyZWxhdGVkIHRyYWl0cywgc3VjaCBhcyBkaWZmZXJlbnQga2luZHMgb2YgY2VsbCBjb3VudHMgKGZvciBleGFtcGxlIGhpZXJhcmNoaWNhbCBwYXJhbWV0ZXJpemF0aW9uIHdpdGhpbiBpbW11bm9sb2dpY2FsIGFzc2F5cykuIEFzIHRob3NlIGRhdGEtcG9pbnRzIGFyZSBub3QgaW5kZXBlbmRlbnQgb2YgZWFjaCBvdGhlciwgIHdlIGNvbmR1Y3RlZCBtZXRhIGFuYWx5c2VzIG9uIHRoZXNlIGNvcnJlbGF0ZWQgcGFyYW1ldGVycyB0byBjb2xsYXBzZSB0aGUgbnVtYmVyIG9mIGxldmVscy4KCiMjIyMgQ29sbGFwc2luZyBhbmQgbWVyZ2luZyBjb3JyZWxhdGVkIHBhcmFtZXRlcnMKCkhlcmUgd2UgZG91YmxlIGNoZWNrIG51bWJlcnMgb2YgdHJhaXQgcGFyYW1ldGVycyBpbiB0aGUgZGF0YXNldAoKYGBge3J9CgptZXRhMSA8LSBtZXRhX2NsZWFuIApsZW5ndGgodW5pcXVlKG1ldGExJHByb2NlZHVyZSkpICMxOApsZW5ndGgodW5pcXVlKG1ldGExJEdyb3VwaW5nVGVybSkpICM5Cmxlbmd0aCh1bmlxdWUobWV0YTEkcGFyYW1ldGVyX2dyb3VwKSkgIyAxNDggbGV2ZWxzLiBUbyBiZSB1c2VkIGFzIGdyb3VwaW5nIGZhY3RvciBmb3IgbWV0YS1tZXRhIGFuYWx5c2lzIC8gY29sbGFwc2luZyBkb3duIGJhc2VkIG9uIHRoaW5ncyB0aGF0IGFyZSBjbGFzc2lmaWVkIGlkZW50aWNhbGx5IGluICJwYXJhbWV0ZXJfZ3JvdXAiIGJ1dCBoYXZlIGRpZmZlcmVudCAicGFyYW1ldGVyX25hbWUiCmxlbmd0aCh1bmlxdWUobWV0YTEkcGFyYW1ldGVyX25hbWUpKSAjMjE4CmBgYAoKIyMjIyBDb3VudCBvZiBudW1iZXIgb2YgcGFyYW1ldGVyIG5hbWVzIChjb3JyZWxhdGVkIHN1Yi10cmFpdHMpIGluIGVhY2ggcGFyYW1ldGVyIGdyb3VwIChwYXJfZ3JvdXBfc2l6ZSkgCgojIyBUYWJsZTogTnVtYmVycyBvZiBjb3JyZWxhdGVkIGFuZCB1bmNvcnJlbGF0ZWQgdHJhaXRzClRoaXMgc2VydmVzIHRvIGlkZW50aWZ5IGFuZCBzZXBhcmF0ZSB0aGUgdHJhaXRzIHRoYXQgYXJlIGNvcnJlbGF0ZWQgZnJvbSB0aGUgZnVsbCBkYXRhc2V0IHRoYXQgY2FuIGJlIHByb2Nlc3NlZCBhcyBpcy4gSWYgdGhlIHNhbXBsZSBzaXplIChuKSBmb3IgYSBnaXZlbiAicGFyYW1ldGVyIGdyb3VwIiBlcXVhbHMgMSwgdGhlIHRyYWl0IGlzIHVuaXF1ZSBhbmQgdW5jb3JyZWxhdGVkLiBBbGwgaW5zdGFuY2VzLCB3aGVyZSB0aGVyZSBhcmUgMiBvciBtb3JlIHRyYWl0cyBhc3NvY2lhdGVkIHdpdGggdGhlIHNhbWUgIHBhcmFtZXRlciBncm91cCAoOTAgY2FzZXMpLCBhcmUgc2VsZWN0ZWQgZm9yIGEgIm1pbmktbWV0YSBhbmFseXNpcyIsIHdoaWNoIHJlbW92ZXMgdGhlIGlzc3VlIG9mIGNvcnJlbGF0aW9uLgoKYGBge3J9CmthYmxlKGNiaW5kKG1ldGExICU+JSBjb3VudChwYXJhbWV0ZXJfZ3JvdXApKSkgJT4lCiAga2FibGVfc3R5bGluZygpICU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiNjAlIiwgaGVpZ2h0ID0gIjIwMHB4IikKYGBgCgpgYGB7cn0KbWV0YTFfc3ViIDwtIG1ldGExICU+JQogICMgYWRkIHN1bW1hcnkgb2YgbnVtYmVyIG9mIHBhcmFtZXRlciBuYW1lcyBpbiBlYWNoIHBhcmFtZXRlciBncm91cAogIGdyb3VwX2J5KHBhcmFtZXRlcl9ncm91cCkgJT4lCiAgbXV0YXRlKHBhcl9ncm91cF9zaXplID0gbGVuZ3RoKHVuaXF1ZShwYXJhbWV0ZXJfbmFtZSkpLCAKICAgICAgICAgc2FtcGxlU2l6ZSA9IGFzLm51bWVyaWMoc2FtcGxlU2l6ZSkpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogICMgQ3JlYXRlIHN1YnNldHMgd2l0aCA+IDEgY291bnQgKHBhcl9ncm91cF9zaXplID4gMSkKICBmaWx0ZXIocGFyX2dyb3VwX3NpemUgPiAxKSAjIDkwIG9ic2VydmF0aW9ucwpgYGAKCiMjIyMgTWV0YS1hbmFseXNlcyBvbiBjb3JyZWxhdGVkIChzdWItKXRyYWl0cywgdXNpbmcgcm9idW1ldGFgIApIZXJlIHdlIHBlcGFyZSB0aGUgc3Vic2V0IG9mIHRoZSBkYXRhICh1c2luZyBuZXN0KCkpLCBhbmQgaW4gdGhpcyBmaXJzdCBzdGVwIHRoZSBtb2RlbCBvZiB0aGUgbWV0YSBhbmFseXNpcyBlZmZlY3Qgc2l6ZXMgYXJlIGNhbGN1bGF0ZWQKCmBgYHtyfQoKbWV0YTFiIDwtCiAgbWV0YTEgJT4lCiAgZ3JvdXBfYnkocGFyYW1ldGVyX2dyb3VwKSAlPiUgCiAgc3VtbWFyaXplKHBhcl9ncm91cF9zaXplID0gbGVuZ3RoKHVuaXF1ZShwYXJhbWV0ZXJfbmFtZSwgbmEucm0gPSBUUlVFKSkpCiN0aGlzIGdpdmVzIGEgc3VtbWFyeSBvZiBudW1iZXIgb2YgcGFyYW1ldGVyIG5hbWVzIGluIGVhY2ggcGFyYW1ldGVyIGdyb3VwLCBub3cgaXQgbmVlZWRzIHRvIGdldCBtZXJnZWQgaXQgYmFjayB0b2dldGhlcgoKCm1ldGExJHBhcl9ncm91cF9zaXplIDwtIG1ldGExYiRwYXJfZ3JvdXBfc2l6ZVttYXRjaChtZXRhMSRwYXJhbWV0ZXJfZ3JvdXAsIG1ldGExYiRwYXJhbWV0ZXJfZ3JvdXApXQoKIyBDcmVhdGUgc3Vic2V0cyB3aXRoID4gMSBjb3VudCAocGFyX2dyb3VwX3NpemUgPiAxKSAKCm1ldGExX3N1YiA8LSBzdWJzZXQobWV0YTEscGFyX2dyb3VwX3NpemUgPjEpICMgOTAgb2JzZXJ2YXRpb25zICAgCm1ldGExX3N1YiRzYW1wbGVTaXplIDwtIGFzLm51bWVyaWMobWV0YTFfc3ViJHNhbXBsZVNpemUpCgojIG5lc3RpbmcKbl9jb3VudCA8LSBtZXRhMV9zdWIgJT4lCiAgZ3JvdXBfYnkocGFyYW1ldGVyX2dyb3VwKSAlPiUKICBtdXRhdGUocmF3X04gPSBzdW0oc2FtcGxlU2l6ZSkpICU+JQogIG5lc3QoKSAlPiUKICB1bmdyb3VwKCkKCm1vZGVsX2NvdW50IDwtIG5fY291bnQgJT4lCiAgbXV0YXRlKAogICAgbW9kZWxfbG5SUiA9IG1hcChkYXRhLCB+IHJvYnUoLngkbG5SUiB+IDEsIGRhdGEgPSAueCwgc3R1ZHludW0gPSAueCRpZCwgbW9kZWx3ZWlnaHRzID0gYygiQ09SUiIpLCByaG8gPSAwLjgsIHNtYWxsID0gVFJVRSwgdmFyLmVmZi5zaXplID0gKC54JGxuUlJfc2UpXjIpKSwKICAgIG1vZGVsX2xuVlIgPSBtYXAoZGF0YSwgfiByb2J1KC54JGxuVlIgfiAxLCBkYXRhID0gLngsIHN0dWR5bnVtID0gLngkaWQsIG1vZGVsd2VpZ2h0cyA9IGMoIkNPUlIiKSwgcmhvID0gMC44LCBzbWFsbCA9IFRSVUUsIHZhci5lZmYuc2l6ZSA9ICgueCRsblZSX3NlKV4yKSksCiAgICBtb2RlbF9sbkNWUiA9IG1hcChkYXRhLCB+IHJvYnUoLngkbG5DVlIgfiAxLCBkYXRhID0gLngsIHN0dWR5bnVtID0gLngkaWQsIG1vZGVsd2VpZ2h0cyA9IGMoIkNPUlIiKSwgcmhvID0gMC44LCBzbWFsbCA9IFRSVUUsIHZhci5lZmYuc2l6ZSA9ICgueCRsbkNWUl9zZSleMikpCiAgKQpgYGAKCiMjIyMgRXh0cmFjdCBhbmQgc2F2ZSBwYXJhbWV0ZXIgZXN0aW1hdGVzOgpGdW5jdGlvbiB0byBjb2xsZWN0IHRoZSBvdXRjb21lcyBvZiB0aGUgIm1pbmkiIG1ldGEgYW5hbHlzaXMKCmBgYHtyfQpjb3VudF9mdW4gPC0gZnVuY3Rpb24obW9kX3N1YikgewogIHJldHVybihjKG1vZF9zdWIkcmVnX3RhYmxlJGIuciwgbW9kX3N1YiRyZWdfdGFibGUkQ0kuTCwgbW9kX3N1YiRyZWdfdGFibGUkQ0kuVSwgbW9kX3N1YiRyZWdfdGFibGUkU0UpKQp9ICMgZXN0aW1hdGUsIGxvd2VyIGNpLCB1cHBlciBjaSwgU0UKYGBgCgpFeHRyYWN0aW9uIG9mIHZhbHVlcyBjcmVhdGVkIGR1cmluZyBNZXRhIGFuYWx5c2lzIHVzaW5nIHJvYnUgbWV0YToKCmBgYHtyfQpyb2J1c3ViX1JSIDwtIG1vZGVsX2NvdW50ICU+JQogIHRyYW5zbXV0ZShwYXJhbWV0ZXJfZ3JvdXAsIGVzdGltYXRlbG5SUiA9IG1hcChtb2RlbF9sblJSLCBjb3VudF9mdW4pKSAlPiUKICBtdXRhdGUociA9IG1hcChlc3RpbWF0ZWxuUlIsIH4gZGF0YS5mcmFtZSh0KC4pKSkpICU+JQogIHVubmVzdChyKSAlPiUKICBzZWxlY3QoLWVzdGltYXRlbG5SUikgJT4lCiAgcHVycnI6OnNldF9uYW1lcyhjKCJwYXJhbWV0ZXJfZ3JvdXAiLCAibG5SUiIsICJsblJSX2xvd2VyIiwgImxuUlJfdXBwZXIiLCAibG5SUl9zZSIpKQoKcm9idXN1Yl9DVlIgPC0gbW9kZWxfY291bnQgJT4lCiAgdHJhbnNtdXRlKHBhcmFtZXRlcl9ncm91cCwgZXN0aW1hdGVsbkNWUiA9IG1hcChtb2RlbF9sbkNWUiwgY291bnRfZnVuKSkgJT4lCiAgbXV0YXRlKHIgPSBtYXAoZXN0aW1hdGVsbkNWUiwgfiBkYXRhLmZyYW1lKHQoLikpKSkgJT4lCiAgdW5uZXN0KHIpICU+JQogIHNlbGVjdCgtZXN0aW1hdGVsbkNWUikgJT4lCiAgcHVycnI6OnNldF9uYW1lcyhjKCJwYXJhbWV0ZXJfZ3JvdXAiLCAibG5DVlIiLCAibG5DVlJfbG93ZXIiLCAibG5DVlJfdXBwZXIiLCAibG5DVlJfc2UiKSkKCnJvYnVzdWJfVlIgPC0gbW9kZWxfY291bnQgJT4lCiAgdHJhbnNtdXRlKHBhcmFtZXRlcl9ncm91cCwgZXN0aW1hdGVsblZSID0gbWFwKG1vZGVsX2xuVlIsIGNvdW50X2Z1bikpICU+JQogIG11dGF0ZShyID0gbWFwKGVzdGltYXRlbG5WUiwgfiBkYXRhLmZyYW1lKHQoLikpKSkgJT4lCiAgdW5uZXN0KHIpICU+JQogIHNlbGVjdCgtZXN0aW1hdGVsblZSKSAlPiUKICBwdXJycjo6c2V0X25hbWVzKGMoInBhcmFtZXRlcl9ncm91cCIsICJsblZSIiwgImxuVlJfbG93ZXIiLCAibG5WUl91cHBlciIsICJsblZSX3NlIikpCgpyb2J1X2FsbCA8LSBmdWxsX2pvaW4ocm9idXN1Yl9DVlIsIHJvYnVzdWJfVlIpICU+JSBmdWxsX2pvaW4oLiwgcm9idXN1Yl9SUikKYGBgCiMjIyMgQ29tYmluZSBkYXRhIApNZXJnZSB0aGUgdHdvIGRhdGEgc2V0cyAodGhlIG5ldyBbcm9idV9hbGxdIGFuZCB0aGUgaW5pdGlhbCBbdW5jb3JyZWxhdGVkIHN1Yi10cmFpdHMgd2l0aCBjb3VudCA9IDFdKSAKCmBgYHtyfQptZXRhX2FsbCA8LSBtZXRhMSAlPiUKICBmaWx0ZXIocGFyX2dyb3VwX3NpemUgPT0gMSkgJT4lCiAgYXNfdGliYmxlKCkKIyBzdHIobWV0YV9hbGwpCiMgc3RyKHJvYnVfYWxsKQojIHdoaWNoKGlzLm5hKG1hdGNoKG5hbWVzKG1ldGFfYWxsKSxuYW1lcyhyb2J1X2FsbCkpKSkgICMgY2hlY2sKCiNTdGVwMTogIENvbHVtbnMgYXJlIG1hdGNoZWQgYnkgbmFtZSAoaW4gb3VyIGNhc2UsICdwYXJhbWV0ZXJfZ3JvdXAnKSwgYW5kIGFueSBtaXNzaW5nIGNvbHVtbnMgd2lsbCBiZSBmaWxsZWQgd2l0aCBOQQpjb21iaW5lZG1ldGEgPC0gYmluZF9yb3dzKHJvYnVfYWxsLCBtZXRhX2FsbCkKIyBnbGltcHNlKGNvbWJpbmVkbWV0YSkKCiMgU3RlcHMgMiYzIChhZGQgaW5mb3JtYXRpb24gYWJvdXQgbnVtYmVyIG9mIHRyYWl0cyBpbiBhIHBhcmFtZXRlciBncm91cCwgcHJvY2VkdXJlLCBhbmQgZ3JvdXBpbmcgdGVybSkgCm1ldGFjb21ibyA8LSBjb21iaW5lZG1ldGEKbWV0YWNvbWJvJGNvdW50cyA8LSBtZXRhMSRwYXJfZ3JvdXBfc2l6ZVttYXRjaChtZXRhY29tYm8kcGFyYW1ldGVyX2dyb3VwLCBtZXRhMSRwYXJhbWV0ZXJfZ3JvdXApXSAKbWV0YWNvbWJvJHByb2NlZHVyZTIgPC0gbWV0YTEkcHJvY2VkdXJlW21hdGNoKG1ldGFjb21ibyRwYXJhbWV0ZXJfZ3JvdXAsIG1ldGExJHBhcmFtZXRlcl9ncm91cCldCm1ldGFjb21ibyRHcm91cGluZ1Rlcm0yIDwtIG1ldGExJEdyb3VwaW5nVGVybVttYXRjaChtZXRhY29tYm8kcGFyYW1ldGVyX2dyb3VwLCBtZXRhMSRwYXJhbWV0ZXJfZ3JvdXApXQoKYGBgCgpDbGVhbi11cCwgcmVvcmRlciwgYW5kIHJlbmFtZSAKCmBgYHtyfQptZXRhY29tYm8gPC0gbWV0YWNvbWJvW2MoInBhcmFtZXRlcl9ncm91cCIsICJjb3VudHMiLCJwcm9jZWR1cmUyIiwiR3JvdXBpbmdUZXJtMiIsICJsbkNWUiIsImxuQ1ZSX2xvd2VyIiwibG5DVlJfdXBwZXIiLCJsbkNWUl9zZSIsImxuVlIiLCJsblZSX2xvd2VyIiwibG5WUl91cHBlciIsImxuVlJfc2UiLCJsblJSIiwibG5SUl9sb3dlciIsImxuUlJfdXBwZXIiLCJsblJSX3NlIildIAoKbmFtZXMobWV0YWNvbWJvKVtuYW1lcyhtZXRhY29tYm8pPT0icHJvY2VkdXJlMiJdIDwtICJwcm9jZWR1cmUiIApuYW1lcyhtZXRhY29tYm8pW25hbWVzKG1ldGFjb21ibyk9PSJHcm91cGluZ1Rlcm0yIl0gPC0gIkdyb3VwaW5nVGVybSIgCgojIFF1aWNrIHByZS1jaGVjayBiZWZvcmUgZG9pbmcgcGxvdHMKbWV0YWNvbWJvICU+JQogIGdyb3VwX2J5KEdyb3VwaW5nVGVybSkgJT4lCiAgZHBseXI6OnN1bW1hcml6ZShNZWFuQ1ZSID0gbWVhbihsbkNWUiksIE1lYW5WUiA9IG1lYW4obG5WUiksIE1lYW5SUiA9IG1lYW4obG5SUikpCmBgYAoKIyBUYWJsZSBmb3IgU0hJTlkgQVBQCgpXZSB1c2UgdGhpcyBjb3JyZWN0ZWQgKGZvciBjb3JyZWxhdGVkIHRyYWl0cykgInJlc3VsdHMiIHRhYmxlLCB3aGljaCBjb250YWlucyBlYWNoIG9mIHRoZSBtZXRhLWFuYWx5dGljIG1lYW5zIGZvciBhbGwgZWZmZWN0IHNpemVzIG9mIGludGVyZXN0LCBmb3IgZnVydGhlciBhbmFseXNlcy4gIFdlIGZ1cnRoZXIgdXNlIHRoaXMgdGFibGUgYXMgcGFydCBvZiB0aGUgU2hpbnkgQXBwLCB3aGljaCBpcyBhYmxlIHRvIHByb3ZpZGUgdGhlIHBlcmNlbnRhZ2UgZGlmZmVyZW5jZXMgYmV0d2VlbiBtYWxlcyBhbmQgZmVtYWxlcyBmb3IgbWVhbiwgdmFyaWFuY2UgYW5kIGNvZWZmaWNpZW50IG9mIHZhcmlhbmNlLiAKClRoaXMgaXMgdGhlIGZ1bGwgcmVzdWx0IGRhdGFzZXQKYGBge3J9CmthYmxlKG1ldGFjb21ibykgJT4lCiAga2FibGVfc3R5bGluZygpICU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICIyMDBweCIpCgojIHRyYWl0X21ldGFfcmVzdWx0cyA8LSB3cml0ZS5jc3YobWV0YWNvbWJvLCBmaWxlID0gImV4cG9ydC90cmFpdF9tZXRhX3Jlc3VsdHMuY3N2IikKYGBgCgojIyAzLiBTZWNvbmQtb3JkZXIgbWV0YSBhbmFseXNpcyBmb3IgZnVuY3Rpb25hbCBncm91cHMKKFNlY3Rpb24gSCBpbiBGaWd1cmUgMyBpbiBtYWluIGFydGljbGUpCgojIyMgUGVyZm9ybWluZyBtZXRhLWFuYWx5c2VzICgzIGZvciBlYWNoIG9mIHRoZSA5IGdyb3VwaW5nIHRlcm1zOiBsbkNWUiwgbG5WUiwgbG5SUikgCiMjIyMgUHJlcGFyYXRpb24gb2YgZGF0YQpOZXN0aW5nLCBjYWxjdWxhdGluZyB0aGUgbnVtYmVyIG9mIHBhcmFtZXRlcnMgd2l0aGluIGVhY2ggZ3JvdXBpbmcgdGVybSwgYW5kIHJ1bm5pbmcgdGhlIG1ldGEtYW5hbHlzaXMKCmBgYHtyfQptZXRhY29tYm9fZmluYWwgPC0gbWV0YWNvbWJvICU+JQogIGdyb3VwX2J5KEdyb3VwaW5nVGVybSkgJT4lCiAgIG5lc3RfbGVnYWN5KCkgICAjIHdlJ3JlIHVzaW5nICduZXN0X2xlZ2FjeScgdG8ga2VlcCBvbGQgc3ludGF4L2Z1bmN0aW9uYWxpdHkKCiMgKipjYWxjdWxhdGUgbnVtYmVyIG9mIHBhcmFtZXRlcnMgcGVyIGdyb3VwaW5nIHRlcm0KCm1ldGFjb21ib19maW5hbCA8LSBtZXRhY29tYm9fZmluYWwgJT4lIG11dGF0ZShwYXJhX3Blcl9Hcm91cGluZ1Rlcm0gPSBtYXBfZGJsKGRhdGEsIG5yb3cpKQoKIyBGb3IgYWxsIGdyb3VwaW5nIHRlcm1zCm1ldGFjb21ib19maW5hbF9hbGwgPC0gbWV0YWNvbWJvICU+JQogIG5lc3RfbGVnYWN5KCkgIyduZXN0X2xlZ2FjeScgdG8ga2VlcCBvbGQgc3ludGF4L2Z1bmN0aW9uYWxpdHkKCiMgKipGaW5hbCBmaXhlZCBlZmZlY3RzIG1ldGEtYW5hbHlzZXMgd2l0aGluIGdyb3VwaW5nIHRlcm1zLCB3aXRoIFNFIG9mIHRoZSBlc3RpbWF0ZQoKb3ZlcmFsbDEgPC0gbWV0YWNvbWJvX2ZpbmFsICU+JQoKICBtdXRhdGUoCiAgICBtb2RlbF9sbkNWUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICAgIHlpID0gLngkbG5DVlIsIHNlaSA9ICgueCRsbkNWUl91cHBlciAtIC54JGxuQ1ZSX2xvd2VyKSAvICgyICogMS45NiksCiAgICAgIGNvbnRyb2wgPSBsaXN0KG9wdGltaXplciA9ICJvcHRpbSIsIG9wdG1ldGhvZCA9ICJOZWxkZXItTWVhZCIsIG1heGl0ID0gMTAwMCksIHZlcmJvc2UgPSBGCiAgICApKSwKICAgIG1vZGVsX2xuVlIgPSBtYXAoZGF0YSwgfiBtZXRhZm9yOjpybWEudW5pKAogICAgICB5aSA9IC54JGxuVlIsIHNlaSA9ICgueCRsblZSX3VwcGVyIC0gLngkbG5WUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgICBjb250cm9sID0gbGlzdChvcHRpbWl6ZXIgPSAib3B0aW0iLCBvcHRtZXRob2QgPSAiTmVsZGVyLU1lYWQiLCBtYXhpdCA9IDEwMDApLCB2ZXJib3NlID0gRgogICAgKSksCiAgICBtb2RlbF9sblJSID0gbWFwKGRhdGEsIH4gbWV0YWZvcjo6cm1hLnVuaSgKICAgICAgeWkgPSAueCRsblJSLCBzZWkgPSAoLngkbG5SUl91cHBlciAtIC54JGxuUlJfbG93ZXIpIC8gKDIgKiAxLjk2KSwKICAgICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICAgICkpCiAgKQoKIyAqKkZpbmFsIGZpeGVkIGVmZmVjdHMgbWV0YS1hbmFseXNlcyBBQ1JPU1MgZ3JvdXBpbmcgdGVybXMsIHdpdGggU0Ugb2YgdGhlIGVzdGltYXRlCgpvdmVyYWxsX2FsbDEgPC0gbWV0YWNvbWJvX2ZpbmFsX2FsbCAlPiUKCiAgbXV0YXRlKAogICAgbW9kZWxfbG5DVlIgPSBtYXAoZGF0YSwgfiBtZXRhZm9yOjpybWEudW5pKAogICAgICB5aSA9IC54JGxuQ1ZSLCBzZWkgPSAoLngkbG5DVlJfdXBwZXIgLSAueCRsbkNWUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgICBjb250cm9sID0gbGlzdChvcHRpbWl6ZXIgPSAib3B0aW0iLCBvcHRtZXRob2QgPSAiTmVsZGVyLU1lYWQiLCBtYXhpdCA9IDEwMDApLCB2ZXJib3NlID0gRgogICAgKSksCiAgICBtb2RlbF9sblZSID0gbWFwKGRhdGEsIH4gbWV0YWZvcjo6cm1hLnVuaSgKICAgICAgeWkgPSAueCRsblZSLCBzZWkgPSAoLngkbG5WUl91cHBlciAtIC54JGxuVlJfbG93ZXIpIC8gKDIgKiAxLjk2KSwKICAgICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICAgICkpLAogICAgbW9kZWxfbG5SUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICAgIHlpID0gLngkbG5SUiwgc2VpID0gKC54JGxuUlJfdXBwZXIgLSAueCRsblJSX2xvd2VyKSAvICgyICogMS45NiksCiAgICAgIGNvbnRyb2wgPSBsaXN0KG9wdGltaXplciA9ICJvcHRpbSIsIG9wdG1ldGhvZCA9ICJOZWxkZXItTWVhZCIsIG1heGl0ID0gMTAwMCksIHZlcmJvc2UgPSBGCiAgICApKQogICkKYGBgCgojIyMgUmUtc3RydWN0dXJpbmcgdGhlIGRhdGEgZm9yIGVhY2ggZ3JvdXBpbmcgdGVybQpXZSBoZXJlIGRlbGV0ZSB1bnVzZWQgdmFyaWFibGVzLCBhbmQgc2VsZWN0IHRoZSByZXNwZWN0aXZlIGVmZmVjdCBzaXplcy4gUGxlYXNlIG5vdGUgLSB0aGUgcmVmZXJlbmNpbmcgb2YgdGhlIGNlbGxzIGRvZXMgTk9UIGRlcGVuZCBvbiBwcmV2aW91cyBvcmRlcmluZyBvZiB0aGUgZGF0YS4gVGhpcyB3b3VsZCBvbmx5IGJlIGFmZmVjdGVkIGlmIHRoZSBvdXRwdXQgc3RydWN0dXJlIGZyb20gbWV0YWZvcjo6cm1hLnVuaSBjaGFuZ2VzLiAKCmBgYHtyfQpCZWhhdmlvdXIgPC0gYXMuZGF0YS5mcmFtZShvdmVyYWxsMSAlPiUgZmlsdGVyKC4sIEdyb3VwaW5nVGVybSA9PSAiQmVoYXZpb3VyIikgJT4lIG11dGF0ZSgKICBsbkNWUiA9IC5bWzRdXVtbMV1dJGIsIGxuQ1ZSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGxuQ1ZSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGxuQ1ZSX3NlID0gLltbNF1dW1sxXV0kc2UsCiAgbG5WUiA9IC5bWzVdXVtbMV1dJGIsIGxuVlJfbG93ZXIgPSAuW1s1XV1bWzFdXSRjaS5sYiwgbG5WUl91cHBlciA9IC5bWzVdXVtbMV1dJGNpLnViLCBsblZSX3NlID0gLltbNV1dW1sxXV0kc2UsCiAgbG5SUiA9IC5bWzZdXVtbMV1dJGIsIGxuUlJfbG93ZXIgPSAuW1s2XV1bWzFdXSRjaS5sYiwgbG5SUl91cHBlciA9IC5bWzZdXVtbMV1dJGNpLnViLCBsblJSX3NlID0gLltbNl1dW1sxXV0kc2UKKSlbLCBjKDEsIDc6MTgpXQoKSW1tdW5vbG9neSA8LSBhcy5kYXRhLmZyYW1lKG92ZXJhbGwxICU+JSBmaWx0ZXIoLiwgR3JvdXBpbmdUZXJtID09ICJJbW11bm9sb2d5IikgJT4lIG11dGF0ZSgKICBsbkNWUiA9IC5bWzRdXVtbMV1dJGIsIGxuQ1ZSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGxuQ1ZSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGxuQ1ZSX3NlID0gLltbNF1dW1sxXV0kc2UsCiAgbG5WUiA9IC5bWzVdXVtbMV1dJGIsIGxuVlJfbG93ZXIgPSAuW1s1XV1bWzFdXSRjaS5sYiwgbG5WUl91cHBlciA9IC5bWzVdXVtbMV1dJGNpLnViLCBsblZSX3NlID0gLltbNV1dW1sxXV0kc2UsCiAgbG5SUiA9IC5bWzZdXVtbMV1dJGIsIGxuUlJfbG93ZXIgPSAuW1s2XV1bWzFdXSRjaS5sYiwgbG5SUl91cHBlciA9IC5bWzZdXVtbMV1dJGNpLnViLCBsblJSX3NlID0gLltbNl1dW1sxXV0kc2UKKSlbLCBjKDEsIDc6MTgpXQoKSGVtYXRvbG9neSA8LSBhcy5kYXRhLmZyYW1lKG92ZXJhbGwxICU+JSBmaWx0ZXIoLiwgR3JvdXBpbmdUZXJtID09ICJIZW1hdG9sb2d5IikgJT4lIG11dGF0ZSgKICBsbkNWUiA9IC5bWzRdXVtbMV1dJGIsIGxuQ1ZSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGxuQ1ZSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGxuQ1ZSX3NlID0gLltbNF1dW1sxXV0kc2UsCiAgbG5WUiA9IC5bWzVdXVtbMV1dJGIsIGxuVlJfbG93ZXIgPSAuW1s1XV1bWzFdXSRjaS5sYiwgbG5WUl91cHBlciA9IC5bWzVdXVtbMV1dJGNpLnViLCBsblZSX3NlID0gLltbNV1dW1sxXV0kc2UsCiAgbG5SUiA9IC5bWzZdXVtbMV1dJGIsIGxuUlJfbG93ZXIgPSAuW1s2XV1bWzFdXSRjaS5sYiwgbG5SUl91cHBlciA9IC5bWzZdXVtbMV1dJGNpLnViLCBsblJSX3NlID0gLltbNl1dW1sxXV0kc2UKKSlbLCBjKDEsIDc6MTgpXQoKSGVhcmluZyA8LSBhcy5kYXRhLmZyYW1lKG92ZXJhbGwxICU+JSBmaWx0ZXIoLiwgR3JvdXBpbmdUZXJtID09ICJIZWFyaW5nIikgJT4lIG11dGF0ZSgKICBsbkNWUiA9IC5bWzRdXVtbMV1dJGIsIGxuQ1ZSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGxuQ1ZSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGxuQ1ZSX3NlID0gLltbNF1dW1sxXV0kc2UsCiAgbG5WUiA9IC5bWzVdXVtbMV1dJGIsIGxuVlJfbG93ZXIgPSAuW1s1XV1bWzFdXSRjaS5sYiwgbG5WUl91cHBlciA9IC5bWzVdXVtbMV1dJGNpLnViLCBsblZSX3NlID0gLltbNV1dW1sxXV0kc2UsCiAgbG5SUiA9IC5bWzZdXVtbMV1dJGIsIGxuUlJfbG93ZXIgPSAuW1s2XV1bWzFdXSRjaS5sYiwgbG5SUl91cHBlciA9IC5bWzZdXVtbMV1dJGNpLnViLCBsblJSX3NlID0gLltbNl1dW1sxXV0kc2UKKSlbLCBjKDEsIDc6MTgpXQoKUGh5c2lvbG9neSA8LSBhcy5kYXRhLmZyYW1lKG92ZXJhbGwxICU+JSBmaWx0ZXIoLiwgR3JvdXBpbmdUZXJtID09ICJQaHlzaW9sb2d5IikgJT4lIG11dGF0ZSgKICBsbkNWUiA9IC5bWzRdXVtbMV1dJGIsIGxuQ1ZSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGxuQ1ZSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGxuQ1ZSX3NlID0gLltbNF1dW1sxXV0kc2UsCiAgbG5WUiA9IC5bWzVdXVtbMV1dJGIsIGxuVlJfbG93ZXIgPSAuW1s1XV1bWzFdXSRjaS5sYiwgbG5WUl91cHBlciA9IC5bWzVdXVtbMV1dJGNpLnViLCBsblZSX3NlID0gLltbNV1dW1sxXV0kc2UsCiAgbG5SUiA9IC5bWzZdXVtbMV1dJGIsIGxuUlJfbG93ZXIgPSAuW1s2XV1bWzFdXSRjaS5sYiwgbG5SUl91cHBlciA9IC5bWzZdXVtbMV1dJGNpLnViLCBsblJSX3NlID0gLltbNl1dW1sxXV0kc2UKKSlbLCBjKDEsIDc6MTgpXQoKTWV0YWJvbGlzbSA8LSBhcy5kYXRhLmZyYW1lKG92ZXJhbGwxICU+JSBmaWx0ZXIoLiwgR3JvdXBpbmdUZXJtID09ICJNZXRhYm9saXNtIikgJT4lIG11dGF0ZSgKICBsbkNWUiA9IC5bWzRdXVtbMV1dJGIsIGxuQ1ZSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGxuQ1ZSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGxuQ1ZSX3NlID0gLltbNF1dW1sxXV0kc2UsCiAgbG5WUiA9IC5bWzVdXVtbMV1dJGIsIGxuVlJfbG93ZXIgPSAuW1s1XV1bWzFdXSRjaS5sYiwgbG5WUl91cHBlciA9IC5bWzVdXVtbMV1dJGNpLnViLCBsblZSX3NlID0gLltbNV1dW1sxXV0kc2UsCiAgbG5SUiA9IC5bWzZdXVtbMV1dJGIsIGxuUlJfbG93ZXIgPSAuW1s2XV1bWzFdXSRjaS5sYiwgbG5SUl91cHBlciA9IC5bWzZdXVtbMV1dJGNpLnViLCBsblJSX3NlID0gLltbNl1dW1sxXV0kc2UKKSlbLCBjKDEsIDc6MTgpXQoKTW9ycGhvbG9neSA8LSBhcy5kYXRhLmZyYW1lKG92ZXJhbGwxICU+JSBmaWx0ZXIoLiwgR3JvdXBpbmdUZXJtID09ICJNb3JwaG9sb2d5IikgJT4lIG11dGF0ZSgKICBsbkNWUiA9IC5bWzRdXVtbMV1dJGIsIGxuQ1ZSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGxuQ1ZSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGxuQ1ZSX3NlID0gLltbNF1dW1sxXV0kc2UsCiAgbG5WUiA9IC5bWzVdXVtbMV1dJGIsIGxuVlJfbG93ZXIgPSAuW1s1XV1bWzFdXSRjaS5sYiwgbG5WUl91cHBlciA9IC5bWzVdXVtbMV1dJGNpLnViLCBsblZSX3NlID0gLltbNV1dW1sxXV0kc2UsCiAgbG5SUiA9IC5bWzZdXVtbMV1dJGIsIGxuUlJfbG93ZXIgPSAuW1s2XV1bWzFdXSRjaS5sYiwgbG5SUl91cHBlciA9IC5bWzZdXVtbMV1dJGNpLnViLCBsblJSX3NlID0gLltbNl1dW1sxXV0kc2UKKSlbLCBjKDEsIDc6MTgpXQoKSGVhcnQgPC0gYXMuZGF0YS5mcmFtZShvdmVyYWxsMSAlPiUgZmlsdGVyKC4sIEdyb3VwaW5nVGVybSA9PSAiSGVhcnQiKSAlPiUgbXV0YXRlKAogIGxuQ1ZSID0gLltbNF1dW1sxXV0kYiwgbG5DVlJfbG93ZXIgPSAuW1s0XV1bWzFdXSRjaS5sYiwgbG5DVlJfdXBwZXIgPSAuW1s0XV1bWzFdXSRjaS51YiwgbG5DVlJfc2UgPSAuW1s0XV1bWzFdXSRzZSwKICBsblZSID0gLltbNV1dW1sxXV0kYiwgbG5WUl9sb3dlciA9IC5bWzVdXVtbMV1dJGNpLmxiLCBsblZSX3VwcGVyID0gLltbNV1dW1sxXV0kY2kudWIsIGxuVlJfc2UgPSAuW1s1XV1bWzFdXSRzZSwKICBsblJSID0gLltbNl1dW1sxXV0kYiwgbG5SUl9sb3dlciA9IC5bWzZdXVtbMV1dJGNpLmxiLCBsblJSX3VwcGVyID0gLltbNl1dW1sxXV0kY2kudWIsIGxuUlJfc2UgPSAuW1s2XV1bWzFdXSRzZQopKVssIGMoMSwgNzoxOCldCgpFeWUgPC0gYXMuZGF0YS5mcmFtZShvdmVyYWxsMSAlPiUgZmlsdGVyKC4sIEdyb3VwaW5nVGVybSA9PSAiRXllIikgJT4lIG11dGF0ZSgKICBsbkNWUiA9IC5bWzRdXVtbMV1dJGIsIGxuQ1ZSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGxuQ1ZSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGxuQ1ZSX3NlID0gLltbNF1dW1sxXV0kc2UsCiAgbG5WUiA9IC5bWzVdXVtbMV1dJGIsIGxuVlJfbG93ZXIgPSAuW1s1XV1bWzFdXSRjaS5sYiwgbG5WUl91cHBlciA9IC5bWzVdXVtbMV1dJGNpLnViLCBsblZSX3NlID0gLltbNV1dW1sxXV0kc2UsCiAgbG5SUiA9IC5bWzZdXVtbMV1dJGIsIGxuUlJfbG93ZXIgPSAuW1s2XV1bWzFdXSRjaS5sYiwgbG5SUl91cHBlciA9IC5bWzZdXVtbMV1dJGNpLnViLCBsblJSX3NlID0gLltbNl1dW1sxXV0kc2UKKSlbLCBjKDEsIDc6MTgpXQoKQWxsIDwtIGFzLmRhdGEuZnJhbWUob3ZlcmFsbF9hbGwxICU+JSBtdXRhdGUoCiAgbG5DVlIgPSAuW1syXV1bWzFdXSRiLCBsbkNWUl9sb3dlciA9IC5bWzJdXVtbMV1dJGNpLmxiLCBsbkNWUl91cHBlciA9IC5bWzJdXVtbMV1dJGNpLnViLCBsbkNWUl9zZSA9IC5bWzJdXVtbMV1dJHNlLCBsblZSID0gLltbM11dW1sxXV0kYiwgbG5WUl9sb3dlciA9IC5bWzNdXVtbMV1dJGNpLmxiLCBsblZSX3VwcGVyID0gLltbM11dW1sxXV0kY2kudWIsIGxuVlJfc2UgPSAuW1szXV1bWzFdXSRzZSwKICBsblJSID0gLltbNF1dW1sxXV0kYiwgbG5SUl9sb3dlciA9IC5bWzRdXVtbMV1dJGNpLmxiLCBsblJSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGxuUlJfc2UgPSAuW1s0XV1bWzFdXSRzZQopKVssIGMoNToxNildCgpBbGwkbG5DVlIgPC0gYXMubnVtZXJpYyhBbGwkbG5DVlIpCkFsbCRsblZSIDwtIGFzLm51bWVyaWMoQWxsJGxuVlIpCkFsbCRsblJSIDwtIGFzLm51bWVyaWMoQWxsJGxuUlIpCkFsbCA8LSBBbGwgJT4lIG11dGF0ZShHcm91cGluZ1Rlcm0gPSAiQWxsIikKCm92ZXJhbGwyIDwtIGJpbmRfcm93cyhCZWhhdmlvdXIsIE1vcnBob2xvZ3ksIE1ldGFib2xpc20sIFBoeXNpb2xvZ3ksIEltbXVub2xvZ3ksIEhlbWF0b2xvZ3ksIEhlYXJ0LCBIZWFyaW5nLCBFeWUsIEFsbCkgI0ZaOiB3YXJuaW5ncyBhcmUgb2sKYGBgCgojIFZpc3VhbGlzYXRpb24KIyMgRmlndXJlIDQgCiMjIyMgUHJlcGFyYXRpb24gZm9yIHBsb3RzOiBDb3VudCBkYXRhLCBiYXNlZCBvbiBGaXJzdC1vcmRlciBtZXRhIGFuYWx5c2lzIHJlc3VsdHMKVGhpcyBpbmNsdWRlcyBhbGwgc2VwYXJhdGUgZWxpZ2libGUgdHJhaXRzLgpSZS1vcmRlcmluZyBvZiBncm91cGluZyB0ZXJtcyAKCmBgYHtyfQoKbWV0YV9jbGVhbiRHcm91cGluZ1Rlcm0gPC0gZmFjdG9yKG1ldGFfY2xlYW4kR3JvdXBpbmdUZXJtLCBsZXZlbHMgPSBjKCJCZWhhdmlvdXIiLCAiTW9ycGhvbG9neSIsICJNZXRhYm9saXNtIiwgIlBoeXNpb2xvZ3kiLCAiSW1tdW5vbG9neSIsICJIZW1hdG9sb2d5IiwgIkhlYXJ0IiwgIkhlYXJpbmciLCAiRXllIikpCm1ldGFfY2xlYW4kR3JvdXBpbmdUZXJtIDwtIGZhY3RvcihtZXRhX2NsZWFuJEdyb3VwaW5nVGVybSwgcmV2KGxldmVscyhtZXRhX2NsZWFuJEdyb3VwaW5nVGVybSkpKQoKIyAqUHJlcGFyaW5nIGRhdGEgZm9yIGFsbCB0cmFpdHMKCm1ldGEucGxvdDIuYWxsIDwtIG1ldGFfY2xlYW4gJT4lCiAgc2VsZWN0KGxuQ1ZSLCBsblZSLCBsblJSLCBHcm91cGluZ1Rlcm0pICU+JQogIGFycmFuZ2UoR3JvdXBpbmdUZXJtKQoKbWV0YS5wbG90Mi5hbGwuYiA8LSBnYXRoZXIobWV0YS5wbG90Mi5hbGwsIHRyYWl0LCB2YWx1ZSwgYyhsbkNWUiwgbG5SUikpICMgbG5WUiBoYXMgYmVlbiByZW1vdmVkIGhlcmUgYW5kIGluIHRoZSBzdGVwcyBiZWxvdywgYXMgdGhpcyBpcyBvbmx5IGluY2x1ZGVkIGluIHRoZSBzdXBwbGVtZW50YWwgZmlndXJlCgptZXRhLnBsb3QyLmFsbC5iJHRyYWl0IDwtIGZhY3RvcihtZXRhLnBsb3QyLmFsbC5iJHRyYWl0LCBsZXZlbHMgPSBjKCJsbkNWUiIsICJsblJSIikpIAptZXRhLnBsb3QyLmFsbC5jIDwtIG1ldGEucGxvdDIuYWxsLmIgJT4lCiAgZ3JvdXBfYnlfYXQodmFycyh0cmFpdCwgR3JvdXBpbmdUZXJtKSkgJT4lCiAgc3VtbWFyaXNlKAogICAgbWFsZWJpYXMgPSBzdW0odmFsdWUgPiAwKSwgZmVtYWxlYmlhcyA9IHN1bSh2YWx1ZSA8PSAwKSwgdG90YWwgPSBtYWxlYmlhcyArIGZlbWFsZWJpYXMsCiAgICBtYWxlcGVyY2VudCA9IG1hbGViaWFzICogMTAwIC8gdG90YWwsIGZlbWFsZXBlcmNlbnQgPSBmZW1hbGViaWFzICogMTAwIC8gdG90YWwKICApCgptZXRhLnBsb3QyLmFsbC5jJGxhYmVsIDwtICJBbGwgdHJhaXRzIgoKIyByZXN0cnVjdHVyZSB0byBjcmVhdGUgc3RhY2tlZCBiYXIgcGxvdHMKCm1ldGEucGxvdDIuYWxsLmQgPC0gYXMuZGF0YS5mcmFtZShtZXRhLnBsb3QyLmFsbC5jKQptZXRhLnBsb3QyLmFsbC5lIDwtIGdhdGhlcihtZXRhLnBsb3QyLmFsbC5kLCBrZXkgPSBzZXgsIHZhbHVlID0gcGVyY2VudCwgbWFsZXBlcmNlbnQ6ZmVtYWxlcGVyY2VudCwgZmFjdG9yX2tleSA9IFRSVUUpCgojIGNyZWF0ZSBuZXcgc2FtcGxlIHNpemUgdmFyaWFibGUKCm1ldGEucGxvdDIuYWxsLmUkc2FtcGxlc2l6ZSA8LSB3aXRoKG1ldGEucGxvdDIuYWxsLmUsIGlmZWxzZShzZXggPT0gIm1hbGVwZXJjZW50IiwgbWFsZWJpYXMsIGZlbWFsZWJpYXMpKQoKIyBhZGQgc3VtbWFyeSByb3cgKCdBbGwnKSBhbmQgcmUtYXJyYW5nZSByb3dzIGludG8gY29ycmVjdCBvcmRlciBmb3IgcGxvdHRpbmcgI0ZaIGFkZGVkCgptZXRhLnBsb3QyLmFsbC5mIDwtIG1ldGEucGxvdDIuYWxsLmUgJT4lIGdyb3VwX2J5KHRyYWl0LCBzZXgpICU+JSAKCXN1bW1hcmlzZShHcm91cGluZ1Rlcm0gPSAiQWxsIiwgbWFsZWJpYXMgPSBzdW0obWFsZWJpYXMpLCBmZW1hbGViaWFzID0gc3VtKGZlbWFsZWJpYXMpLCB0b3RhbCA9IG1hbGViaWFzICsgZmVtYWxlYmlhcywgCglsYWJlbCA9ICJBbGwgdHJhaXRzIiwgc2FtcGxlc2l6ZSA9IHN1bShzYW1wbGVzaXplKSkgJT4lCgltdXRhdGUocGVyY2VudCA9IGlmZWxzZShzZXggPT0gImZlbWFsZXBlcmNlbnQiLCBmZW1hbGViaWFzKjEwMC8obWFsZWJpYXMrZmVtYWxlYmlhcyksIG1hbGViaWFzKjEwMC8obWFsZWJpYXMrZmVtYWxlYmlhcykpKSAlPiUKCWJpbmRfcm93cyhtZXRhLnBsb3QyLmFsbC5lLCAuKSAlPiUKCW11dGF0ZShyb3dudW1iZXIgPSByb3dfbnVtYmVyKCkpICU+JQoJLltjKDM3LCAxOjksIDM5LCAxMDoxOCwgMzgsIDE5OjI3LCA0MCwgMjg6MzYpLCBdCgptZXRhLnBsb3QyLmFsbC5mJEdyb3VwaW5nVGVybSA8LSBmYWN0b3IobWV0YS5wbG90Mi5hbGwuZiRHcm91cGluZ1Rlcm0sIGxldmVscyA9IGMoIkJlaGF2aW91ciIsICJNb3JwaG9sb2d5IiwgIk1ldGFib2xpc20iLCAiUGh5c2lvbG9neSIsICJJbW11bm9sb2d5IiwgIkhlbWF0b2xvZ3kiLCAiSGVhcnQiLCAiSGVhcmluZyIsICJFeWUiLCAiQWxsIikpIAptZXRhLnBsb3QyLmFsbC5mJEdyb3VwaW5nVGVybSA8LSBmYWN0b3IobWV0YS5wbG90Mi5hbGwuZiRHcm91cGluZ1Rlcm0sIHJldihsZXZlbHMobWV0YS5wbG90Mi5hbGwuZiRHcm91cGluZ1Rlcm0pKSkKCm1hbGViaWFzX0ZpZzJfYWxsdHJhaXRzIDwtCiAgZ2dwbG90KG1ldGEucGxvdDIuYWxsLmYpICsKICBhZXMoeCA9IEdyb3VwaW5nVGVybSwgeSA9IHBlcmNlbnQsIGZpbGwgPSBzZXgpICsKICBnZW9tX2NvbCgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA1MCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JheTQwIikgKwogIGdlb21fdGV4dCgKICAgIGRhdGEgPSBzdWJzZXQobWV0YS5wbG90Mi5hbGwuZiwgc2FtcGxlc2l6ZSAhPSAwKSwgYWVzKGxhYmVsID0gc2FtcGxlc2l6ZSksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAuNSksCiAgICBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAzLjUKICApICsKICBmYWNldF9ncmlkKAogICAgY29scyA9IHZhcnModHJhaXQpLCByb3dzID0gdmFycyhsYWJlbCksIGxhYmVsbGVyID0gbGFiZWxfd3JhcF9nZW4od2lkdGggPSAxOCksCiAgICBzY2FsZXMgPSAiZnJlZSIsIHNwYWNlID0gImZyZWUiCiAgKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDE4KSArCiAgdGhlbWUoCiAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNzAsIHNpemUgPSAxMCwgbWFyZ2luID0gbWFyZ2luKHQgPSAxNSwgciA9IDE1LCBiID0gMTUsIGwgPSAxNSkpLAogICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5VTEwsIGxpbmV0eXBlID0gImJsYW5rIiwgZmlsbCA9ICJncmF5OTAiKSwKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDAuNSwgImxpbmVzIiksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG91ciA9ICJncmF5OTUiKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG9yID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpCiAgKSArCiAgY29vcmRfZmxpcCgpCgojIG1hbGViaWFzX0ZpZzJfYWxsdHJhaXRzICAgICAjKHBhbmVsIEEgaW4gRmlndXJlIDQgaW4gbXMpCmBgYAoKCiMjIyAgT3ZlcmFsbCByZXN1bHRzIG9mIHNlY29uZCBvcmRlciBtZXRhIGFuYWx5c2lzIChGaWd1cmUgNCwgUGFuZWwgQikKIyMjIyBSZXN0cnVjdHVyZSBkYXRhIGZvciBwbG90dGluZyAKRGF0YSBhcmUgcmVzdHJ1Y3R1cmVkLCBhbmQgZ3JvdXBpbmcgdGVybXMgYXJlIGJlaW5nIHJlLW9yZGVyZWQKCmBgYHtyfQpvdmVyYWxsMyA8LSBnYXRoZXIob3ZlcmFsbDIsIHBhcmFtZXRlciwgdmFsdWUsIGMobG5DVlIsIGxuUlIpLCBmYWN0b3Jfa2V5ID0gVFJVRSkgIyBsblZSLAoKbG5DVlIuY2kgPC0gb3ZlcmFsbDMgJT4lCiAgZmlsdGVyKHBhcmFtZXRlciA9PSAibG5DVlIiKSAlPiUKICBtdXRhdGUoY2kubG93ID0gbG5DVlJfbG93ZXIsIGNpLmhpZ2ggPSBsbkNWUl91cHBlcikKbG5WUi5jaSA8LSBvdmVyYWxsMyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJsblZSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuVlJfbG93ZXIsIGNpLmhpZ2ggPSBsblZSX3VwcGVyKQpsblJSLmNpIDwtIG92ZXJhbGwzICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuUlIiKSAlPiUKICBtdXRhdGUoY2kubG93ID0gbG5SUl9sb3dlciwgY2kuaGlnaCA9IGxuUlJfdXBwZXIpCgpvdmVyYWxsNCA8LSBiaW5kX3Jvd3MobG5DVlIuY2ksIGxuUlIuY2kpICU+JSBzZWxlY3QoR3JvdXBpbmdUZXJtLCBwYXJhbWV0ZXIsIHZhbHVlLCBjaS5sb3csIGNpLmhpZ2gpICMgbG5WUi5jaSwKCiMgcmUtb3JkZXIgR3JvdXBpbmcgVGVybXMKCm92ZXJhbGw0JEdyb3VwaW5nVGVybSA8LSBmYWN0b3Iob3ZlcmFsbDQkR3JvdXBpbmdUZXJtLCBsZXZlbHMgPSBjKCJCZWhhdmlvdXIiLCAiTW9ycGhvbG9neSIsICJNZXRhYm9saXNtIiwgIlBoeXNpb2xvZ3kiLCAiSW1tdW5vbG9neSIsICJIZW1hdG9sb2d5IiwgIkhlYXJ0IiwgIkhlYXJpbmciLCAiRXllIiwgIkFsbCIpKQpvdmVyYWxsNCRHcm91cGluZ1Rlcm0gPC0gZmFjdG9yKG92ZXJhbGw0JEdyb3VwaW5nVGVybSwgcmV2KGxldmVscyhvdmVyYWxsNCRHcm91cGluZ1Rlcm0pKSkKb3ZlcmFsbDQkbGFiZWwgPC0gIkFsbCB0cmFpdHMiCgprYWJsZShjYmluZChvdmVyYWxsNCwgb3ZlcmFsbDQpKSAlPiUKICBrYWJsZV9zdHlsaW5nKCkgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjIwMHB4IikKYGBgCgpgYGB7cn0KTWV0YW1ldGFfRmlnM19hbGx0cmFpdHMgPC0gb3ZlcmFsbDQgJT4lCgogIGdncGxvdChhZXMoeSA9IEdyb3VwaW5nVGVybSwgeCA9IHZhbHVlKSkgKwogIGdlb21fZXJyb3JiYXJoKGFlcygKICAgIHhtaW4gPSBjaS5sb3csCiAgICB4bWF4ID0gY2kuaGlnaAogICksCiAgaGVpZ2h0ID0gMC4xLCBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBwYXJhbWV0ZXIpLAogICAgZmlsbCA9ICJibGFjayIsCiAgICBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyLjIsCiAgICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgc2NhbGVfeF9jb250aW51b3VzKAogICAgbGltaXRzID0gYygtMC4yNCwgMC4yNSksCiAgICBicmVha3MgPSBjKC0wLjIsIC0wLjEsIDAsIDAuMSwgMC4yKSwKICAgIG5hbWUgPSAiRWZmZWN0IHNpemUiCiAgKSArCiAgZ2VvbV92bGluZSgKICAgIHhpbnRlcmNlcHQgPSAwLAogICAgY29sb3IgPSAiYmxhY2siLAogICAgbGluZXR5cGUgPSAiZGFzaGVkIgogICkgKwogIGZhY2V0X2dyaWQoCiAgICBjb2xzID0gdmFycyhwYXJhbWV0ZXIpLCByb3dzID0gdmFycyhsYWJlbCksCiAgICBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMjMpLAogICAgc2NhbGVzID0gImZyZWUiLAogICAgc3BhY2UgPSAiZnJlZSIKICApICsKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgc2l6ZSA9IDEwLCBtYXJnaW4gPSBtYXJnaW4odCA9IDE1LCByID0gMTUsIGIgPSAxNSwgbCA9IDE1KSksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTlVMTCwgbGluZXR5cGUgPSAiYmxhbmsiLCBmaWxsID0gImdyYXk5MCIpLAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMC41LCAibGluZXMiKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZSgpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3VyID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3IgPSAiZ3JheTk1IiksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNCksCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkKICApCgojIE1ldGFtZXRhX0ZpZzNfYWxsdHJhaXRzCmBgYAoKIyMjIEZpZyA0CkpvaW4gdGhlIGRpZmZlcmVudCBwYXJ0cyBhbmQgICNUTyBETyEhIGFkZCBNIC8gRiBzeW1ib2xzIGluIE1ldGFtZXRhX0ZpZzNfYWxsdHJhaXRzIApgYGB7cn0KI1Rlc3QKI21hbGUgPC0gcmVhZFBORyhzeXN0ZW0uZmlsZSgiaW1nIiwgIm1hbGUiKSkKI3Rlc3QgPC0gTWV0YW1ldGFfRmlnM19hbGx0cmFpdHMgCgojbGlicmFyeShwbmcpCmBgYAoKCmBgYHtyfQpGaWc0IDwtIGdnYXJyYW5nZShtYWxlYmlhc19GaWcyX2FsbHRyYWl0cywgTWV0YW1ldGFfRmlnM19hbGx0cmFpdHMsICBucm93ID0gMiwgYWxpZ24gPSAidiIsIGhlaWdodHMgPSBjKDEsIDEpLCBsYWJlbHMgPSBjKCJBIiwgIkIiKSkKRmlnNAoKYGBgCgojIyMgRmlndXJlIDQ6IApQYW5lbCBBIHNob3dzIHRoZSBudW1iZXJzIG9mIHRyYWl0cyBhY3Jvc3MgZnVuY3Rpb25hbCBncm91cHMgdGhhdCBhcmUgZWl0aGVyIG1hbGUtYmlhc2VkIChibHVlLWdyZWVuKSBvciBmZW1hbGUtYmlhc2VkIChvcmFuZ2UtcmVkKSwgYXMgY2FsY3VsYXRlZCBpbiBTdGVwIEQgKGZpZ3VyZSAzKS4gUGFuZWwgQiBzaG93cyBlZmZlY3Qgc2l6ZXMgYW5kIDk1JSBDSSBmcm9tIHNlcGFyYXRlIG1ldGEtYW5hbHlzaXMgZm9yIGVhY2ggZnVuY3Rpb25hbCBncm91cCAoc3RlcCBIIGluIEZpZ3VyZSAzKS4gQm90aCBwYW5lbHMgcmVwcmVzZW50IHJlc3VsdHMgZXZhbHVhdGVkIGFjcm9zcyBhbGwgdHJhaXRzIChQaGFzZSAzLCBGaWd1cmUgMykuIFRyYWl0cyB0aGF0IGFyZSBtYWxlIGJpYXNlZCBhcmUgTWFsZSBkYXRhIGlzIHNob3duIGluIGJsdWUsIHdoZXJlYXMgZmVtYWxlIGJpYXMgZGF0YSBpcyByZXByZXNlbnRlZCBpbiBvcmFuZ2UuCgoKCiMjIEZpZ3VyZSA1CiMjIyMgUHJlcGFyaW5nIGRhdGEgZm9yIHRyYWl0cyB3aXRoIENJIG5vdCBvdmVybGFwcGluZyAwClRvIGZ1cnRoZXIgaW52ZXN0aWdhdGUgc2V4IGJpYXMgaW4gdGhpcyBkYXRhc2V0LCBhbmQgaW4gcGFydGljdWxhciBpZiB0aGUgZXh0ZW50IG9mIHNleCBiaWFzIGRpZmZlcnMgYmV0d2VlbiB0cmFpdHMsIHdlIGludmVzdGlnYXRlIHRoZSBtYWduaXR1ZGUgb2YgbWFsZS0gYW5kIGZlbWFsZSBiaWFzIGluIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IHRyYWl0cyBvbiAoYm90aCBmb3IgbWVhbnMgYW5kIHZhcmlhYmlsaXR5KQoKVG8gZG8gdGhpcywgd2Ugc2VsZWN0IG9ubHkgdHJhaXRzIHRoYXQgaGF2ZSBDSXMgdGhhdCBkbyBub3Qgb3ZlcmxhcCB3aXRoIHplcm8uCiMjIyBGRUxJWDogIkFMTCIgbWlzc2luZy4gIFRoaXMgZmlndXJlIGlzIHBhbmVsIEEgaW4gRmlnIDUKYGBge3J9CgptZXRhLnBsb3QyLnNpZyA8LSBtZXRhX2NsZWFuICU+JQogIG11dGF0ZSgKICAgIGxuQ1ZSc2lnID0gaWZlbHNlKGxuQ1ZSX2xvd2VyICogbG5DVlJfdXBwZXIgPiAwLCAxLCAwKSwgbG5WUnNpZyA9IGlmZWxzZShsblZSX2xvd2VyICogbG5WUl91cHBlciA+IDAsIDEsIDApLAogICAgbG5SUnNpZyA9IGlmZWxzZShsblJSX2xvd2VyICogbG5SUl91cHBlciA+IDAsIDEsIDApCiAgKQoKbWV0YS5wbG90Mi5zaWcuYiA8LSBtZXRhLnBsb3QyLnNpZ1ssIGMoImxuQ1ZSIiwgImxuUlIiLCAibG5DVlJzaWciLCAibG5WUnNpZyIsICJsblJSc2lnIiwgIkdyb3VwaW5nVGVybSIpXSAjICJsblZSIiwKCm1ldGEucGxvdDIuc2lnLmMgPC0gZ2F0aGVyKG1ldGEucGxvdDIuc2lnLmIsIHRyYWl0LCB2YWx1ZSwgbG5DVlI6bG5SUikKbWV0YS5wbG90Mi5zaWcuYyRzaWcgPC0gInBsYWNlaG9sZGVyIgoKbWV0YS5wbG90Mi5zaWcuYyR0cmFpdCA8LSBmYWN0b3IobWV0YS5wbG90Mi5zaWcuYyR0cmFpdCwgbGV2ZWxzID0gYygibG5DVlIiLCAibG5SUiIpKSAjICJsblZSIiwKCm1ldGEucGxvdDIuc2lnLmMkc2lnIDwtIGlmZWxzZShtZXRhLnBsb3QyLnNpZy5jJHRyYWl0ID09ICJsbkNWUiIsIG1ldGEucGxvdDIuc2lnLmMkbG5DVlJzaWcsCiAgaWZlbHNlKG1ldGEucGxvdDIuc2lnLmMkdHJhaXQgPT0gImxuVlIiLCBtZXRhLnBsb3QyLnNpZy5jJGxuVlJzaWcsIG1ldGEucGxvdDIuc2lnLmMkbG5SUnNpZykKKQoKIyBjaG9vc2luZyBzZXggYmlhc2VkIGxuLXJhdGlvcyBzaWduaWZpY2FudGx5IGxhcmdlciB0aGFuIDAKbWV0YS5wbG90Mi5zaWcubWFsZWJpYXMgPC0gbWV0YS5wbG90Mi5zaWcuYyAlPiUKICBncm91cF9ieV9hdCh2YXJzKHRyYWl0LCBHcm91cGluZ1Rlcm0pKSAlPiUKICBmaWx0ZXIoc2lnID09IDEpICU+JQogIHN1bW1hcmlzZShtYWxlX3NpZyA9IHN1bSh2YWx1ZSA+IDApLCBmZW1hbGVfc2lnID0gc3VtKHZhbHVlIDwgMCksIHRvdGFsID0gbWFsZV9zaWcgKyBmZW1hbGVfc2lnKQoKbWV0YS5wbG90Mi5zaWcubWFsZWJpYXMgPC0gdW5ncm91cChtZXRhLnBsb3QyLnNpZy5tYWxlYmlhcykgJT4lCiAgYWRkX3Jvdyh0cmFpdCA9ICJsbkNWUiIsIEdyb3VwaW5nVGVybSA9ICJIZWFyaW5nIiwgbWFsZV9zaWcgPSAwLCBmZW1hbGVfc2lnID0gMCwgLmJlZm9yZSA9IDQpICU+JSAjIGFkZCAiSGVhcmluZyIgZm9yIGxuQ1ZSIChub3QgZmlsdGVyZWQgYXMgb25seSB6ZXJvcykKICBtdXRhdGUobWFsZXBlcmNlbnQgPSBtYWxlX3NpZyAqIDEwMCAvIHRvdGFsLCBmZW1hbGVwZXJjZW50ID0gZmVtYWxlX3NpZyAqIDEwMCAvIHRvdGFsKQoKbWV0YS5wbG90Mi5zaWcubWFsZWJpYXMkbGFiZWwgPC0gIkNJIG5vdCBvdmVybGFwcGluZyB6ZXJvIgoKIyByZXN0cnVjdHVyZSB0byBjcmVhdGUgc3RhY2tlZCBiYXIgcGxvdHMKCm1ldGEucGxvdDIuc2lnLmJvdGhzZXhlcyA8LSBhcy5kYXRhLmZyYW1lKG1ldGEucGxvdDIuc2lnLm1hbGViaWFzKQptZXRhLnBsb3QyLnNpZy5ib3Roc2V4ZXMuYiA8LSBnYXRoZXIobWV0YS5wbG90Mi5zaWcuYm90aHNleGVzLCBrZXkgPSBzZXgsIHZhbHVlID0gcGVyY2VudCwgbWFsZXBlcmNlbnQ6ZmVtYWxlcGVyY2VudCwgZmFjdG9yX2tleSA9IFRSVUUpCgojIGNyZWF0ZSBuZXcgc2FtcGxlIHNpemUgdmFyaWFibGUKCm1ldGEucGxvdDIuc2lnLmJvdGhzZXhlcy5iJHNhbXBsZXNpemUgPC0gd2l0aChtZXRhLnBsb3QyLnNpZy5ib3Roc2V4ZXMuYiwgaWZlbHNlKHNleCA9PSAibWFsZXBlcmNlbnQiLCBtYWxlX3NpZywgZmVtYWxlX3NpZykpCgojIFBsb3QgRmlnMiBhbGwgc2lnbmlmaWNhbnQgcmVzdWx0cyAoQ0kgbm90IG92ZXJsYXBwaW5nIHplcm8pOgojIFNldmVyYWwgZ3JvdWluZyB0ZXJtcyBhcmUgYWRkZWQgcG9zdC1ob2MgKHdpdGggbm8gZGF0YSB0byBkaXNwbGF5KTogbm8gc2lnbmlmaWNhbnQgbG5DVlIgZm9yICdIZWFyaW5nJyBpbiBlaXRoZXIgc2V4OyBubyBzaWcuIG1hbGUtYmlhc2VkIGxuQ1ZSIGZvciAnSW1tdW5vbG9neScgYW5kICdFeWUsIGFuZCBubyBzaWduaWZpY2FudCBtYWxlLWJpYXNlZCBsblZSIGZvciAnRXllJy4KCm1hbGViaWFzX0ZpZzJfc2lndHJhaXRzIDwtCiAgZ2dwbG90KG1ldGEucGxvdDIuc2lnLmJvdGhzZXhlcy5iKSArCiAgYWVzKHggPSBHcm91cGluZ1Rlcm0sIHkgPSBwZXJjZW50LCBmaWxsID0gc2V4KSArCiAgZ2VvbV9jb2woKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNTAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImdyYXk0MCIpICsKICBnZW9tX3RleHQoCiAgICBkYXRhID0gc3Vic2V0KG1ldGEucGxvdDIuc2lnLmJvdGhzZXhlcy5iLCBzYW1wbGVzaXplICE9IDApLCBhZXMobGFiZWwgPSBzYW1wbGVzaXplKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSwKICAgIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDMuNQogICkgKwogIGZhY2V0X2dyaWQoCiAgICBjb2xzID0gdmFycyh0cmFpdCksIHJvd3MgPSB2YXJzKGxhYmVsKSwgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDE4KSwKICAgIHNjYWxlcyA9ICJmcmVlIiwgc3BhY2UgPSAiZnJlZSIKICApICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTgpICsKICB0aGVtZSgKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgc2l6ZSA9IDEwLCBtYXJnaW4gPSBtYXJnaW4odCA9IDE1LCByID0gMTUsIGIgPSAxNSwgbCA9IDE1KSksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTlVMTCwgbGluZXR5cGUgPSAiYmxhbmsiLCBmaWxsID0gImdyYXk5MCIpLAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMC41LCAibGluZXMiKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZSgpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3VyID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3IgPSAiZ3JheTk1IiksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkKICApICsKICBjb29yZF9mbGlwKCkKYGBgCgoKIyMjIFByZXBhcmF0aW9uIGZvciBQbG90cyBvbiBzaWduaWZpY2FudCBzZXgtYmlhcyAoU2Vjb25kLW9yZGVyIG1ldGEgYW5hbHlzaXMgcmVzdWx0cwoKIyMjIyBGaWd1cmUgNSBCIC0gdHJhaXRzIHdpdGggQ0kgbm90IG92ZXJsYXBwaW5nIDAgClByZXBhcmUgZGF0YSAKY3JlYXRlIGNvbHVtbiB3aXRoIDE9IGRpZmZlcmVudCBmcm9tIHplcm8sIDA9IHplcm8gaW5jbHVkZWQgaW4gQ0kKIyMjIyBNYWxlLWJpYXNlZCAoc2lnbmlmaWNhbnQpIHRyYWl0cwoKYGBge3J9Cm1ldGEubWFsZS5wbG90My5zaWcgPC0gbWV0YWNvbWJvICU+JQogIG11dGF0ZSgKICAgIHNpZ0NWUiA9IGlmZWxzZShsbkNWUl9sb3dlciA+IDAsIDEsIDApLAogICAgc2lnVlIgPSBpZmVsc2UobG5WUl9sb3dlciA+IDAsIDEsIDApLAogICAgc2lnUlIgPSBpZmVsc2UobG5SUl9sb3dlciA+IDAsIDEsIDApCiAgKQoKIyBTaWduaWZpY2FudCBzdWJzZXQgZm9yIGxuQ1ZSCm1ldGFjb21ib19tYWxlLnBsb3QzLkNWUiA8LSBtZXRhLm1hbGUucGxvdDMuc2lnICU+JQogIGZpbHRlcihzaWdDVlIgPT0gMSkgJT4lCiAgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBuZXN0KCkKCm1ldGFjb21ib19tYWxlLnBsb3QzLkNWUi5hbGwgPC0gbWV0YS5tYWxlLnBsb3QzLnNpZyAlPiUKICBmaWx0ZXIoc2lnQ1ZSID09IDEpICU+JQogIG5lc3QoKQoKIyBTaWduaWZpY2FudCBzdWJzZXQgZm9yIGxuVlIKbWV0YWNvbWJvX21hbGUucGxvdDMuVlIgPC0gbWV0YS5tYWxlLnBsb3QzLnNpZyAlPiUKICBmaWx0ZXIoc2lnVlIgPT0gMSkgJT4lCiAgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBuZXN0KCkKCm1ldGFjb21ib19tYWxlLnBsb3QzLlZSLmFsbCA8LSBtZXRhLm1hbGUucGxvdDMuc2lnICU+JQogIGZpbHRlcihzaWdWUiA9PSAxKSAlPiUKICBuZXN0KCkKCiMgU2lnbmlmaWNhbnQgc3Vic2V0IGZvciBsblJSCm1ldGFjb21ib19tYWxlLnBsb3QzLlJSIDwtIG1ldGEubWFsZS5wbG90My5zaWcgJT4lCiAgZmlsdGVyKHNpZ1JSID09IDEpICU+JQogIGdyb3VwX2J5KEdyb3VwaW5nVGVybSkgJT4lCiAgbmVzdCgpCgptZXRhY29tYm9fbWFsZS5wbG90My5SUi5hbGwgPC0gbWV0YS5tYWxlLnBsb3QzLnNpZyAlPiUKICBmaWx0ZXIoc2lnUlIgPT0gMSkgJT4lCiAgbmVzdCgpCgojICoqRmluYWwgZml4ZWQgZWZmZWN0cyBtZXRhLWFuYWx5c2VzIHdpdGhpbiBncm91cGluZyB0ZXJtcywgd2l0aCBTRSBvZiB0aGUgZXN0aW1hdGUKCnBsb3QzLm1hbGUubWV0YS5DVlIgPC0gbWV0YWNvbWJvX21hbGUucGxvdDMuQ1ZSICU+JQogIG11dGF0ZShtb2RlbF9sbkNWUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuQ1ZSLCBzZWkgPSAoLngkbG5DVlJfdXBwZXIgLSAueCRsbkNWUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCnBsb3QzLm1hbGUubWV0YS5WUiA8LSBtZXRhY29tYm9fbWFsZS5wbG90My5WUiAlPiUKICBtdXRhdGUobW9kZWxfbG5WUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuVlIsIHNlaSA9ICgueCRsblZSX3VwcGVyIC0gLngkbG5WUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCnBsb3QzLm1hbGUubWV0YS5SUiA8LSBtZXRhY29tYm9fbWFsZS5wbG90My5SUiAlPiUKICBtdXRhdGUobW9kZWxfbG5SUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuUlIsIHNlaSA9ICgueCRsblJSX3VwcGVyIC0gLngkbG5SUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCiMgQWNyb3NzIGFsbCBncm91cGluZyB0ZXJtcyAjCgpwbG90My5tYWxlLm1ldGEuQ1ZSLmFsbCA8LSBtZXRhY29tYm9fbWFsZS5wbG90My5DVlIuYWxsICU+JQogIG11dGF0ZShtb2RlbF9sbkNWUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuQ1ZSLCBzZWkgPSAoLngkbG5DVlJfdXBwZXIgLSAueCRsbkNWUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCnBsb3QzLm1hbGUubWV0YS5DVlIuYWxsIDwtIHBsb3QzLm1hbGUubWV0YS5DVlIuYWxsICU+JSBtdXRhdGUoR3JvdXBpbmdUZXJtID0gIkFsbCIpCgpwbG90My5tYWxlLm1ldGEuVlIuYWxsIDwtIG1ldGFjb21ib19tYWxlLnBsb3QzLlZSLmFsbCAlPiUKICBtdXRhdGUobW9kZWxfbG5WUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuVlIsIHNlaSA9ICgueCRsblZSX3VwcGVyIC0gLngkbG5WUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCnBsb3QzLm1hbGUubWV0YS5WUi5hbGwgPC0gcGxvdDMubWFsZS5tZXRhLlZSLmFsbCAlPiUgbXV0YXRlKEdyb3VwaW5nVGVybSA9ICJBbGwiKQoKcGxvdDMubWFsZS5tZXRhLlJSLmFsbCA8LSBtZXRhY29tYm9fbWFsZS5wbG90My5SUi5hbGwgJT4lCiAgbXV0YXRlKG1vZGVsX2xuUlIgPSBtYXAoZGF0YSwgfiBtZXRhZm9yOjpybWEudW5pKAogICAgeWkgPSAueCRsblJSLCBzZWkgPSAoLngkbG5SUl91cHBlciAtIC54JGxuUlJfbG93ZXIpIC8gKDIgKiAxLjk2KSwKICAgIGNvbnRyb2wgPSBsaXN0KG9wdGltaXplciA9ICJvcHRpbSIsIG9wdG1ldGhvZCA9ICJOZWxkZXItTWVhZCIsIG1heGl0ID0gMTAwMCksIHZlcmJvc2UgPSBGCiAgKSkpCgpwbG90My5tYWxlLm1ldGEuUlIuYWxsIDwtIHBsb3QzLm1hbGUubWV0YS5SUi5hbGwgJT4lIG11dGF0ZShHcm91cGluZ1Rlcm0gPSAiQWxsIikKCiMgQ29tYmluZSB3aXRoIHNlcGFyYXRlIGdyb3VwaW5nIHRlcm0gcmVzdWx0cwoKcGxvdDMubWFsZS5tZXRhLkNWUiA8LSBiaW5kX3Jvd3MocGxvdDMubWFsZS5tZXRhLkNWUiwgcGxvdDMubWFsZS5tZXRhLkNWUi5hbGwpCnBsb3QzLm1hbGUubWV0YS5WUiA8LSBiaW5kX3Jvd3MocGxvdDMubWFsZS5tZXRhLlZSLCBwbG90My5tYWxlLm1ldGEuVlIuYWxsKQpwbG90My5tYWxlLm1ldGEuUlIgPC0gYmluZF9yb3dzKHBsb3QzLm1hbGUubWV0YS5SUiwgcGxvdDMubWFsZS5tZXRhLlJSLmFsbCkKCiMgKipSZS1zdHJ1Y3R1cmUgZGF0YSBmb3IgZWFjaCBncm91cGluZyB0ZXJtOyBkZWxldGUgdW4tdXNlZCB2YXJpYWJsZXMKCnBsb3QzLm1hbGUubWV0YS5DVlIuYiA8LSBhcy5kYXRhLmZyYW1lKHBsb3QzLm1hbGUubWV0YS5DVlIgJT4lIGdyb3VwX2J5KEdyb3VwaW5nVGVybSkgJT4lCiAgbXV0YXRlKAogICAgbG5DVlIgPSBtYXBfZGJsKG1vZGVsX2xuQ1ZSLCBwbHVjaygyKSksIGxuQ1ZSX2xvd2VyID0gbWFwX2RibChtb2RlbF9sbkNWUiwgcGx1Y2soNikpLAogICAgbG5DVlJfdXBwZXIgPSBtYXBfZGJsKG1vZGVsX2xuQ1ZSLCBwbHVjayg3KSksIGxuQ1ZSX3NlID0gbWFwX2RibChtb2RlbF9sbkNWUiwgcGx1Y2soMykpCiAgKSlbLCBjKDEsIDQ6NyldCmFkZC5yb3cuaGVhcmluZyA8LSBhcy5kYXRhLmZyYW1lKHQoYygiSGVhcmluZyIsIE5BLCBOQSwgTkEsIE5BKSkpICU+JSBzZXROYW1lcyhuYW1lcyhwbG90My5tYWxlLm1ldGEuQ1ZSLmIpKQoKcGxvdDMubWFsZS5tZXRhLkNWUi5iIDwtIGJpbmRfcm93cyhwbG90My5tYWxlLm1ldGEuQ1ZSLmIsIGFkZC5yb3cuaGVhcmluZykKcGxvdDMubWFsZS5tZXRhLkNWUi5iIDwtIHBsb3QzLm1hbGUubWV0YS5DVlIuYltvcmRlcihwbG90My5tYWxlLm1ldGEuQ1ZSLmIkR3JvdXBpbmdUZXJtKSwgXQoKcGxvdDMubWFsZS5tZXRhLlZSLmIgPC0gYXMuZGF0YS5mcmFtZShwbG90My5tYWxlLm1ldGEuVlIgJT4lIGdyb3VwX2J5KEdyb3VwaW5nVGVybSkgJT4lCiAgbXV0YXRlKAogICAgbG5WUiA9IG1hcF9kYmwobW9kZWxfbG5WUiwgcGx1Y2soMikpLCBsblZSX2xvd2VyID0gbWFwX2RibChtb2RlbF9sblZSLCBwbHVjayg2KSksCiAgICBsblZSX3VwcGVyID0gbWFwX2RibChtb2RlbF9sblZSLCBwbHVjayg3KSksIGxuVlJfc2UgPSBtYXBfZGJsKG1vZGVsX2xuVlIsIHBsdWNrKDMpKQogICkpWywgYygxLCA0OjcpXQpwbG90My5tYWxlLm1ldGEuVlIuYiA8LSBwbG90My5tYWxlLm1ldGEuVlIuYltvcmRlcihwbG90My5tYWxlLm1ldGEuVlIuYiRHcm91cGluZ1Rlcm0pLCBdCgpwbG90My5tYWxlLm1ldGEuUlIuYiA8LSBhcy5kYXRhLmZyYW1lKHBsb3QzLm1hbGUubWV0YS5SUiAlPiUgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBtdXRhdGUoCiAgICBsblJSID0gbWFwX2RibChtb2RlbF9sblJSLCBwbHVjaygyKSksIGxuUlJfbG93ZXIgPSBtYXBfZGJsKG1vZGVsX2xuUlIsIHBsdWNrKDYpKSwKICAgIGxuUlJfdXBwZXIgPSBtYXBfZGJsKG1vZGVsX2xuUlIsIHBsdWNrKDcpKSwgbG5SUl9zZSA9IG1hcF9kYmwobW9kZWxfbG5SUiwgcGx1Y2soMykpCiAgKSlbLCBjKDEsIDQ6NyldCnBsb3QzLm1hbGUubWV0YS5SUi5iIDwtIHBsb3QzLm1hbGUubWV0YS5SUi5iW29yZGVyKHBsb3QzLm1hbGUubWV0YS5SUi5iJEdyb3VwaW5nVGVybSksIF0KCm92ZXJhbGwubWFsZS5wbG90MyA8LSBmdWxsX2pvaW4ocGxvdDMubWFsZS5tZXRhLkNWUi5iLCBwbG90My5tYWxlLm1ldGEuVlIuYikKb3ZlcmFsbC5tYWxlLnBsb3QzIDwtIGZ1bGxfam9pbihvdmVyYWxsLm1hbGUucGxvdDMsIHBsb3QzLm1hbGUubWV0YS5SUi5iKQoKb3ZlcmFsbC5tYWxlLnBsb3QzJEdyb3VwaW5nVGVybSA8LSBmYWN0b3Iob3ZlcmFsbC5tYWxlLnBsb3QzJEdyb3VwaW5nVGVybSwgbGV2ZWxzID0gYygiQmVoYXZpb3VyIiwgIk1vcnBob2xvZ3kiLCAiTWV0YWJvbGlzbSIsICJQaHlzaW9sb2d5IiwgIkltbXVub2xvZ3kiLCAiSGVtYXRvbG9neSIsICJIZWFydCIsICJIZWFyaW5nIiwgIkV5ZSIsICJBbGwiKSkKb3ZlcmFsbC5tYWxlLnBsb3QzJEdyb3VwaW5nVGVybSA8LSBmYWN0b3Iob3ZlcmFsbC5tYWxlLnBsb3QzJEdyb3VwaW5nVGVybSwgcmV2KGxldmVscyhvdmVyYWxsLm1hbGUucGxvdDMkR3JvdXBpbmdUZXJtKSkpCgojIGFkZCBtaXNzaW5nIEdyb3VwaW5nVGVybXMgZm9yIHBsb3QKb3ZlcmFsbC5tYWxlLnBsb3QzIDwtIGFkZF9yb3cob3ZlcmFsbC5tYWxlLnBsb3QzLCBHcm91cGluZ1Rlcm0gPSAiQmVoYXZpb3VyIikKb3ZlcmFsbC5tYWxlLnBsb3QzIDwtIGFkZF9yb3cob3ZlcmFsbC5tYWxlLnBsb3QzLCBHcm91cGluZ1Rlcm0gPSAiSW1tdW5vbG9neSIpCm92ZXJhbGwubWFsZS5wbG90MyA8LSBhZGRfcm93KG92ZXJhbGwubWFsZS5wbG90MywgR3JvdXBpbmdUZXJtID0gIkV5ZSIpCgpvdmVyYWxsLm1hbGUucGxvdDMkR3JvdXBpbmdUZXJtIDwtIGZhY3RvcihvdmVyYWxsLm1hbGUucGxvdDMkR3JvdXBpbmdUZXJtLCBsZXZlbHMgPSBjKCJCZWhhdmlvdXIiLCAiTW9ycGhvbG9neSIsICJNZXRhYm9saXNtIiwgIlBoeXNpb2xvZ3kiLCAiSW1tdW5vbG9neSIsICJIZW1hdG9sb2d5IiwgIkhlYXJ0IiwgIkhlYXJpbmciLCAiRXllIiwgIkFsbCIpKQpvdmVyYWxsLm1hbGUucGxvdDMkR3JvdXBpbmdUZXJtIDwtIGZhY3RvcihvdmVyYWxsLm1hbGUucGxvdDMkR3JvdXBpbmdUZXJtLCByZXYobGV2ZWxzKG92ZXJhbGwubWFsZS5wbG90MyRHcm91cGluZ1Rlcm0pKSkKCiMgc3RyKG92ZXJhbGwubWFsZS5wbG90MykKYGBgCgoKUmVzdHJ1Y3R1cmUgTUFMRSBkYXRhIGZvciBwbG90dGluZyAKCmBgYHtyfQpvdmVyYWxsMy5tYWxlLnNpZyA8LSBnYXRoZXIob3ZlcmFsbC5tYWxlLnBsb3QzLCBwYXJhbWV0ZXIsIHZhbHVlLCBjKGxuQ1ZSLCBsblJSKSwgZmFjdG9yX2tleSA9IFRSVUUpICMgbG5WUiwKCmxuQ1ZSLmNpIDwtIG92ZXJhbGwzLm1hbGUuc2lnICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuQ1ZSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuQ1ZSX2xvd2VyLCBjaS5oaWdoID0gbG5DVlJfdXBwZXIpCiMgbG5WUi5jaSA8LSBvdmVyYWxsMy5tYWxlLnNpZyAgJT4lIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuVlIiKSAlPiUgbXV0YXRlKGNpLmxvdyA9IGxuVlJfbG93ZXIsIGNpLmhpZ2ggPSBsblZSX3VwcGVyKQpsblJSLmNpIDwtIG92ZXJhbGwzLm1hbGUuc2lnICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuUlIiKSAlPiUKICBtdXRhdGUoY2kubG93ID0gbG5SUl9sb3dlciwgY2kuaGlnaCA9IGxuUlJfdXBwZXIpCgpvdmVyYWxsNC5tYWxlLnNpZyA8LSBiaW5kX3Jvd3MobG5DVlIuY2ksIGxuUlIuY2kpICU+JSBzZWxlY3QoR3JvdXBpbmdUZXJtLCBwYXJhbWV0ZXIsIHZhbHVlLCBjaS5sb3csIGNpLmhpZ2gpICMgbG5WUi5jaSwKCm92ZXJhbGw0Lm1hbGUuc2lnJGxhYmVsIDwtICJDSSBub3Qgb3ZlcmxhcHBpbmcgemVybyIKYGBgCgpQbG90IEZpZzViIGFsbCBzaWduaWZpY2FudCByZXN1bHRzIChDSSBub3Qgb3ZlcmxhcHBpbmcgemVybykgZm9yIG1hbGVzCgpgYGB7cn0KCk1ldGFtZXRhX0ZpZzNfbWFsZS5zaWcgPC0gb3ZlcmFsbDQubWFsZS5zaWcgJT4lCiAgZ2dwbG90KGFlcyh5ID0gR3JvdXBpbmdUZXJtLCB4ID0gdmFsdWUpKSArCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKAogICAgeG1pbiA9IGNpLmxvdywKICAgIHhtYXggPSBjaS5oaWdoCiAgKSwKICBoZWlnaHQgPSAwLjEsIHNob3cubGVnZW5kID0gRkFMU0UKICApICsKICBnZW9tX3BvaW50KGFlcyhzaGFwZSA9IHBhcmFtZXRlciksCiAgICBmaWxsID0gIm1lZGl1bWFxdWFtYXJpbmUiLCBjb2xvciA9ICJtZWRpdW1hcXVhbWFyaW5lIiwgc2l6ZSA9IDIuMiwKICAgIHNob3cubGVnZW5kID0gRkFMU0UKICApICsKICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICBsaW1pdHMgPSBjKDAsIDAuNCksCiAgICBicmVha3MgPSBjKDAsIDAuMyksCiAgICBuYW1lID0gIkVmZmVjdCBzaXplIgogICkgKwogIGdlb21fdmxpbmUoCiAgICB4aW50ZXJjZXB0ID0gMCwKICAgIGNvbG9yID0gImJsYWNrIiwKICAgIGxpbmV0eXBlID0gImRhc2hlZCIKICApICsKICBmYWNldF9ncmlkKAogICAgY29scyA9IHZhcnMocGFyYW1ldGVyKSwgcm93cyA9IHZhcnMobGFiZWwpLAogICAgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDIzKSwKICAgIHNjYWxlcyA9ICJmcmVlIiwKICAgIHNwYWNlID0gImZyZWUiCiAgKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoCiAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNzAsIHNpemUgPSAxMCwgbWFyZ2luID0gbWFyZ2luKHQgPSAxNSwgciA9IDE1LCBiID0gMTUsIGwgPSAxNSkpLAogICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5VTEwsIGxpbmV0eXBlID0gImJsYW5rIiwgZmlsbCA9ICJncmF5OTAiKSwKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDAuNSwgImxpbmVzIiksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG91ciA9ICJncmF5OTUiKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG9yID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpCiAgKQoKIyBNZXRhbWV0YV9GaWczX21hbGUuc2lnCmBgYAoKIyMjIyBGZW1hbGUgcGFydCwgc2lnbmlmaWNhbnQgdHJhaXRzCkZlbWFsZSBGaWc1QiBzaWcKClByZXBhcmUgZGF0YSBmb3IgdHJhaXRzIHdpdGggQ0kgbm90IG92ZXJsYXBwaW5nIDAKY3JlYXRlIGNvbHVtbiB3aXRoIDE9IGRpZmZlcmVudCBmcm9tIHplcm8sIDA9IHplcm8gaW5jbHVkZWQgaW4gQ0kKCmBgYHtyfQoKIyBmZW1hbGUtYmlhc2VkIHRyYWl0cwoKbWV0YS5mZW1hbGUucGxvdDMuc2lnIDwtIG1ldGFjb21ibyAlPiUKICBtdXRhdGUoCiAgICBzaWdDVlIgPSBpZmVsc2UobG5DVlJfdXBwZXIgPCAwLCAxLCAwKSwKICAgIHNpZ1ZSID0gaWZlbHNlKGxuVlJfdXBwZXIgPCAwLCAxLCAwKSwKICAgIHNpZ1JSID0gaWZlbHNlKGxuUlJfdXBwZXIgPCAwLCAxLCAwKQogICkKCiMgU2lnbmlmaWNhbnQgc3Vic2V0IGZvciBsbkNWUgoKbWV0YWNvbWJvX2ZlbWFsZS5wbG90My5DVlIgPC0gbWV0YS5mZW1hbGUucGxvdDMuc2lnICU+JQogIGZpbHRlcihzaWdDVlIgPT0gMSkgJT4lCiAgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBuZXN0KCkKCm1ldGFjb21ib19mZW1hbGUucGxvdDMuQ1ZSLmFsbCA8LSBtZXRhLmZlbWFsZS5wbG90My5zaWcgJT4lCiAgZmlsdGVyKHNpZ0NWUiA9PSAxKSAlPiUKICBuZXN0KCkKCiMgU2lnbmlmaWNhbnQgc3Vic2V0IGZvciBsblZSCgptZXRhY29tYm9fZmVtYWxlLnBsb3QzLlZSIDwtIG1ldGEuZmVtYWxlLnBsb3QzLnNpZyAlPiUKICBmaWx0ZXIoc2lnVlIgPT0gMSkgJT4lCiAgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBuZXN0KCkKCm1ldGFjb21ib19mZW1hbGUucGxvdDMuVlIuYWxsIDwtIG1ldGEuZmVtYWxlLnBsb3QzLnNpZyAlPiUKICBmaWx0ZXIoc2lnVlIgPT0gMSkgJT4lCiAgbmVzdCgpCgojIFNpZ25pZmljYW50IHN1YnNldCBmb3IgbG5SUgoKbWV0YWNvbWJvX2ZlbWFsZS5wbG90My5SUiA8LSBtZXRhLmZlbWFsZS5wbG90My5zaWcgJT4lCiAgZmlsdGVyKHNpZ1JSID09IDEpICU+JQogIGdyb3VwX2J5KEdyb3VwaW5nVGVybSkgJT4lCiAgbmVzdCgpCgptZXRhY29tYm9fZmVtYWxlLnBsb3QzLlJSLmFsbCA8LSBtZXRhLmZlbWFsZS5wbG90My5zaWcgJT4lCiAgZmlsdGVyKHNpZ1JSID09IDEpICU+JQogIG5lc3QoKQoKIyAqKkZpbmFsIGZpeGVkIGVmZmVjdHMgbWV0YS1hbmFseXNlcyB3aXRoaW4gZ3JvdXBpbmcgdGVybXMsIHdpdGggU0Ugb2YgdGhlIGVzdGltYXRlCgpwbG90My5mZW1hbGUubWV0YS5DVlIgPC0gbWV0YWNvbWJvX2ZlbWFsZS5wbG90My5DVlIgJT4lCiAgbXV0YXRlKG1vZGVsX2xuQ1ZSID0gbWFwKGRhdGEsIH4gbWV0YWZvcjo6cm1hLnVuaSgKICAgIHlpID0gLngkbG5DVlIsIHNlaSA9ICgueCRsbkNWUl91cHBlciAtIC54JGxuQ1ZSX2xvd2VyKSAvICgyICogMS45NiksCiAgICBjb250cm9sID0gbGlzdChvcHRpbWl6ZXIgPSAib3B0aW0iLCBvcHRtZXRob2QgPSAiTmVsZGVyLU1lYWQiLCBtYXhpdCA9IDEwMDApLCB2ZXJib3NlID0gRgogICkpKQoKcGxvdDMuZmVtYWxlLm1ldGEuVlIgPC0gbWV0YWNvbWJvX2ZlbWFsZS5wbG90My5WUiAlPiUKICBtdXRhdGUobW9kZWxfbG5WUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuVlIsIHNlaSA9ICgueCRsblZSX3VwcGVyIC0gLngkbG5WUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCnBsb3QzLmZlbWFsZS5tZXRhLlJSIDwtIG1ldGFjb21ib19mZW1hbGUucGxvdDMuUlIgJT4lCiAgbXV0YXRlKG1vZGVsX2xuUlIgPSBtYXAoZGF0YSwgfiBtZXRhZm9yOjpybWEudW5pKAogICAgeWkgPSAueCRsblJSLCBzZWkgPSAoLngkbG5SUl91cHBlciAtIC54JGxuUlJfbG93ZXIpIC8gKDIgKiAxLjk2KSwKICAgIGNvbnRyb2wgPSBsaXN0KG9wdGltaXplciA9ICJvcHRpbSIsIG9wdG1ldGhvZCA9ICJOZWxkZXItTWVhZCIsIG1heGl0ID0gMTAwMCksIHZlcmJvc2UgPSBGCiAgKSkpCgojIEFjcm9zcyBhbGwgZ3JvdXBpbmcgdGVybXMgIwoKcGxvdDMuZmVtYWxlLm1ldGEuQ1ZSLmFsbCA8LSBtZXRhY29tYm9fZmVtYWxlLnBsb3QzLkNWUi5hbGwgJT4lCiAgbXV0YXRlKG1vZGVsX2xuQ1ZSID0gbWFwKGRhdGEsIH4gbWV0YWZvcjo6cm1hLnVuaSgKICAgIHlpID0gLngkbG5DVlIsIHNlaSA9ICgueCRsbkNWUl91cHBlciAtIC54JGxuQ1ZSX2xvd2VyKSAvICgyICogMS45NiksCiAgICBjb250cm9sID0gbGlzdChvcHRpbWl6ZXIgPSAib3B0aW0iLCBvcHRtZXRob2QgPSAiTmVsZGVyLU1lYWQiLCBtYXhpdCA9IDEwMDApLCB2ZXJib3NlID0gRgogICkpKQoKcGxvdDMuZmVtYWxlLm1ldGEuQ1ZSLmFsbCA8LSBwbG90My5mZW1hbGUubWV0YS5DVlIuYWxsICU+JSBtdXRhdGUoR3JvdXBpbmdUZXJtID0gIkFsbCIpCgpwbG90My5mZW1hbGUubWV0YS5WUi5hbGwgPC0gbWV0YWNvbWJvX2ZlbWFsZS5wbG90My5WUi5hbGwgJT4lCiAgbXV0YXRlKG1vZGVsX2xuVlIgPSBtYXAoZGF0YSwgfiBtZXRhZm9yOjpybWEudW5pKAogICAgeWkgPSAueCRsblZSLCBzZWkgPSAoLngkbG5WUl91cHBlciAtIC54JGxuVlJfbG93ZXIpIC8gKDIgKiAxLjk2KSwKICAgIGNvbnRyb2wgPSBsaXN0KG9wdGltaXplciA9ICJvcHRpbSIsIG9wdG1ldGhvZCA9ICJOZWxkZXItTWVhZCIsIG1heGl0ID0gMTAwMCksIHZlcmJvc2UgPSBGCiAgKSkpCgpwbG90My5mZW1hbGUubWV0YS5WUi5hbGwgPC0gcGxvdDMuZmVtYWxlLm1ldGEuVlIuYWxsICU+JSBtdXRhdGUoR3JvdXBpbmdUZXJtID0gIkFsbCIpCgpwbG90My5mZW1hbGUubWV0YS5SUi5hbGwgPC0gbWV0YWNvbWJvX2ZlbWFsZS5wbG90My5SUi5hbGwgJT4lCiAgbXV0YXRlKG1vZGVsX2xuUlIgPSBtYXAoZGF0YSwgfiBtZXRhZm9yOjpybWEudW5pKAogICAgeWkgPSAueCRsblJSLCBzZWkgPSAoLngkbG5SUl91cHBlciAtIC54JGxuUlJfbG93ZXIpIC8gKDIgKiAxLjk2KSwKICAgIGNvbnRyb2wgPSBsaXN0KG9wdGltaXplciA9ICJvcHRpbSIsIG9wdG1ldGhvZCA9ICJOZWxkZXItTWVhZCIsIG1heGl0ID0gMTAwMCksIHZlcmJvc2UgPSBGCiAgKSkpCgpwbG90My5mZW1hbGUubWV0YS5SUi5hbGwgPC0gcGxvdDMuZmVtYWxlLm1ldGEuUlIuYWxsICU+JSBtdXRhdGUoR3JvdXBpbmdUZXJtID0gIkFsbCIpCgojIENvbWJpbmUgd2l0aCBzZXBhcmF0ZSBncm91cGluZyB0ZXJtIHJlc3VsdHMKCnBsb3QzLmZlbWFsZS5tZXRhLkNWUiA8LSBiaW5kX3Jvd3MocGxvdDMuZmVtYWxlLm1ldGEuQ1ZSLCBwbG90My5mZW1hbGUubWV0YS5DVlIuYWxsKQpwbG90My5mZW1hbGUubWV0YS5WUiA8LSBiaW5kX3Jvd3MocGxvdDMuZmVtYWxlLm1ldGEuVlIsIHBsb3QzLmZlbWFsZS5tZXRhLlZSLmFsbCkKcGxvdDMuZmVtYWxlLm1ldGEuUlIgPC0gYmluZF9yb3dzKHBsb3QzLmZlbWFsZS5tZXRhLlJSLCBwbG90My5mZW1hbGUubWV0YS5SUi5hbGwpCgojICoqUmUtc3RydWN0dXJlIGRhdGEgZm9yIGVhY2ggZ3JvdXBpbmcgdGVybTsgZGVsZXRlIHVuLXVzZWQgdmFyaWFibGVzCgpwbG90My5mZW1hbGUubWV0YS5DVlIuYiA8LSBhcy5kYXRhLmZyYW1lKHBsb3QzLmZlbWFsZS5tZXRhLkNWUiAlPiUgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBtdXRhdGUoCiAgICBsbkNWUiA9IG1hcF9kYmwobW9kZWxfbG5DVlIsIHBsdWNrKDIpKSwgbG5DVlJfbG93ZXIgPSBtYXBfZGJsKG1vZGVsX2xuQ1ZSLCBwbHVjayg2KSksCiAgICBsbkNWUl91cHBlciA9IG1hcF9kYmwobW9kZWxfbG5DVlIsIHBsdWNrKDcpKSwgbG5DVlJfc2UgPSBtYXBfZGJsKG1vZGVsX2xuQ1ZSLCBwbHVjaygzKSkKICApKVssIGMoMSwgNDo3KV0KCmFkZC5yb3cuaGVhcmluZyA8LSBhcy5kYXRhLmZyYW1lKHQoYygiSGVhcmluZyIsIE5BLCBOQSwgTkEsIE5BKSkpICU+JSBzZXROYW1lcyhuYW1lcyhwbG90My5mZW1hbGUubWV0YS5DVlIuYikpCgpwbG90My5mZW1hbGUubWV0YS5DVlIuYiA8LSBiaW5kX3Jvd3MocGxvdDMuZmVtYWxlLm1ldGEuQ1ZSLmIsIGFkZC5yb3cuaGVhcmluZykKcGxvdDMuZmVtYWxlLm1ldGEuQ1ZSLmIgPC0gcGxvdDMuZmVtYWxlLm1ldGEuQ1ZSLmJbb3JkZXIocGxvdDMuZmVtYWxlLm1ldGEuQ1ZSLmIkR3JvdXBpbmdUZXJtKSwgXQoKcGxvdDMuZmVtYWxlLm1ldGEuVlIuYiA8LSBhcy5kYXRhLmZyYW1lKHBsb3QzLmZlbWFsZS5tZXRhLlZSICU+JSBncm91cF9ieShHcm91cGluZ1Rlcm0pICU+JQogIG11dGF0ZSgKICAgIGxuVlIgPSBtYXBfZGJsKG1vZGVsX2xuVlIsIHBsdWNrKDIpKSwgbG5WUl9sb3dlciA9IG1hcF9kYmwobW9kZWxfbG5WUiwgcGx1Y2soNikpLAogICAgbG5WUl91cHBlciA9IG1hcF9kYmwobW9kZWxfbG5WUiwgcGx1Y2soNykpLCBsblZSX3NlID0gbWFwX2RibChtb2RlbF9sblZSLCBwbHVjaygzKSkKICApKVssIGMoMSwgNDo3KV0KCnBsb3QzLmZlbWFsZS5tZXRhLlZSLmIgPC0gcGxvdDMuZmVtYWxlLm1ldGEuVlIuYltvcmRlcihwbG90My5mZW1hbGUubWV0YS5WUi5iJEdyb3VwaW5nVGVybSksIF0KCnBsb3QzLmZlbWFsZS5tZXRhLlJSLmIgPC0gYXMuZGF0YS5mcmFtZShwbG90My5mZW1hbGUubWV0YS5SUiAlPiUgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBtdXRhdGUoCiAgICBsblJSID0gbWFwX2RibChtb2RlbF9sblJSLCBwbHVjaygyKSksIGxuUlJfbG93ZXIgPSBtYXBfZGJsKG1vZGVsX2xuUlIsIHBsdWNrKDYpKSwKICAgIGxuUlJfdXBwZXIgPSBtYXBfZGJsKG1vZGVsX2xuUlIsIHBsdWNrKDcpKSwgbG5SUl9zZSA9IG1hcF9kYmwobW9kZWxfbG5SUiwgcGx1Y2soMykpCiAgKSlbLCBjKDEsIDQ6NyldCgpwbG90My5mZW1hbGUubWV0YS5SUi5iIDwtIHBsb3QzLmZlbWFsZS5tZXRhLlJSLmJbb3JkZXIocGxvdDMuZmVtYWxlLm1ldGEuUlIuYiRHcm91cGluZ1Rlcm0pLCBdCgpvdmVyYWxsLmZlbWFsZS5wbG90MyA8LSBmdWxsX2pvaW4ocGxvdDMuZmVtYWxlLm1ldGEuQ1ZSLmIsIHBsb3QzLmZlbWFsZS5tZXRhLlZSLmIpCm92ZXJhbGwuZmVtYWxlLnBsb3QzIDwtIGZ1bGxfam9pbihvdmVyYWxsLmZlbWFsZS5wbG90MywgcGxvdDMuZmVtYWxlLm1ldGEuUlIuYikKCm92ZXJhbGwuZmVtYWxlLnBsb3QzJEdyb3VwaW5nVGVybSA8LSBmYWN0b3Iob3ZlcmFsbC5mZW1hbGUucGxvdDMkR3JvdXBpbmdUZXJtLCBsZXZlbHMgPSBjKCJCZWhhdmlvdXIiLCAiTW9ycGhvbG9neSIsICJNZXRhYm9saXNtIiwgIlBoeXNpb2xvZ3kiLCAiSW1tdW5vbG9neSIsICJIZW1hdG9sb2d5IiwgIkhlYXJ0IiwgIkhlYXJpbmciLCAiRXllIiwgIkFsbCIpKQpvdmVyYWxsLmZlbWFsZS5wbG90MyRHcm91cGluZ1Rlcm0gPC0gZmFjdG9yKG92ZXJhbGwuZmVtYWxlLnBsb3QzJEdyb3VwaW5nVGVybSwgcmV2KGxldmVscyhvdmVyYWxsLmZlbWFsZS5wbG90MyRHcm91cGluZ1Rlcm0pKSkKYGBgCgpSZXN0cnVjdHVyZSBkYXRhIGZvciBwbG90dGluZwoKYGBge3J9Cm92ZXJhbGwzLmZlbWFsZS5zaWcgPC0gZ2F0aGVyKG92ZXJhbGwuZmVtYWxlLnBsb3QzLCBwYXJhbWV0ZXIsIHZhbHVlLCBjKGxuQ1ZSLCBsblJSKSwgZmFjdG9yX2tleSA9IFRSVUUpICMgbG5WUiwKCmxuQ1ZSLmNpIDwtIG92ZXJhbGwzLmZlbWFsZS5zaWcgJT4lCiAgZmlsdGVyKHBhcmFtZXRlciA9PSAibG5DVlIiKSAlPiUKICBtdXRhdGUoY2kubG93ID0gbG5DVlJfbG93ZXIsIGNpLmhpZ2ggPSBsbkNWUl91cHBlcikKIyBsblZSLmNpIDwtIG92ZXJhbGwzLmZlbWFsZS5zaWcgICU+JSBmaWx0ZXIocGFyYW1ldGVyID09ICJsblZSIikgJT4lIG11dGF0ZShjaS5sb3cgPSBsblZSX2xvd2VyLCBjaS5oaWdoID0gbG5WUl91cHBlcikKbG5SUi5jaSA8LSBvdmVyYWxsMy5mZW1hbGUuc2lnICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuUlIiKSAlPiUKICBtdXRhdGUoY2kubG93ID0gbG5SUl9sb3dlciwgY2kuaGlnaCA9IGxuUlJfdXBwZXIpCgpvdmVyYWxsNC5mZW1hbGUuc2lnIDwtIGJpbmRfcm93cyhsbkNWUi5jaSwgbG5SUi5jaSkgJT4lIHNlbGVjdChHcm91cGluZ1Rlcm0sIHBhcmFtZXRlciwgdmFsdWUsIGNpLmxvdywgY2kuaGlnaCkgIyBsblZSLmNpLAoKb3ZlcmFsbDQuZmVtYWxlLnNpZyRsYWJlbCA8LSAiQ0kgbm90IG92ZXJsYXBwaW5nIHplcm8iCmBgYAoKUGxvdHRpbmcgRmlnNUIgYWxsIHNpZ25pZmljYW50IHJlc3VsdHMgKENJIG5vdCBvdmVybGFwcGluZyB6ZXJvLCBmZW1hbGUgKQoKYGBge3J9CgpNZXRhbWV0YV9GaWczX2ZlbWFsZS5zaWcgPC0gb3ZlcmFsbDQuZmVtYWxlLnNpZyAlPiUKICBnZ3Bsb3QoYWVzKHkgPSBHcm91cGluZ1Rlcm0sIHggPSB2YWx1ZSkpICsKICBnZW9tX2Vycm9yYmFyaChhZXMoCiAgICB4bWluID0gY2kubG93LAogICAgeG1heCA9IGNpLmhpZ2gKICApLAogIGhlaWdodCA9IDAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRQogICkgKwogIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gcGFyYW1ldGVyKSwKICAgIGZpbGwgPSAic2FsbW9uMSIsIGNvbG9yID0gInNhbG1vbjEiLCBzaXplID0gMi4yLAogICAgc2hvdy5sZWdlbmQgPSBGQUxTRQogICkgKwogIHNjYWxlX3hfY29udGludW91cygKICAgIGxpbWl0cyA9IGMoLTAuNCwgMCksCiAgICBicmVha3MgPSBjKC0wLjMsIDApLAogICAgbmFtZSA9ICJFZmZlY3Qgc2l6ZSIKICApICsKICBnZW9tX3ZsaW5lKAogICAgeGludGVyY2VwdCA9IDAsCiAgICBjb2xvciA9ICJibGFjayIsCiAgICBsaW5ldHlwZSA9ICJkYXNoZWQiCiAgKSArCiAgZmFjZXRfZ3JpZCgKICAgIGNvbHMgPSB2YXJzKHBhcmFtZXRlciksICMgcm93cyA9IHZhcnMobGFiZWwpLAogICAgIyBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMjMpLAogICAgc2NhbGVzID0gImZyZWUiLAogICAgc3BhY2UgPSAiZnJlZSIKICApICsKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgc2l6ZSA9IDEwLCBtYXJnaW4gPSBtYXJnaW4odCA9IDE1LCByID0gMTUsIGIgPSAxNSwgbCA9IDE1KSksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTlVMTCwgbGluZXR5cGUgPSAiYmxhbmsiLCBmaWxsID0gImdyYXk5MCIpLAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMC41LCAibGluZXMiKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZSgpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3VyID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3IgPSAiZ3JheTk1IiksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkKICApCgojIE1ldGFtZXRhX0ZpZzNfZmVtYWxlLnNpZyAjKEZpZ3VyZSA1QiBsZWZ0IHBhbmVsKQpgYGAKIyMgSk9JTiEhISBDT0RFIE1JU1NJTkc/PwoKCgojIFN1cHBsZW1lbnRhbCBQbG90cwojIyBGaWd1cmUgUzEgCiMjIyBJbmNsdWRpbmcgbG5WUgojIyMgQ291bnQgZGF0YSwgaW5jbHVkaW5nIGxuVlIgKEZpZyBTMSBwYW5lbCBBKQoKYGBge3J9CiMgKlByZXBhcmUgZGF0YSBmb3IgYWxsIHRyYWl0cwoKbWV0YS5wbG90Mi5hbGwgPC0gbWV0YV9jbGVhbiAlPiUKICBzZWxlY3QobG5DVlIsIGxuVlIsIGxuUlIsIEdyb3VwaW5nVGVybSkgJT4lCiAgYXJyYW5nZShHcm91cGluZ1Rlcm0pCgptZXRhLnBsb3QyLmFsbC5iUzEgPC0gZ2F0aGVyKG1ldGEucGxvdDIuYWxsLCB0cmFpdCwgdmFsdWUsIGMobG5DVlIsIGxuVlIsIGxuUlIpKQoKbWV0YS5wbG90Mi5hbGwuYlMxJHRyYWl0IDwtIGZhY3RvcihtZXRhLnBsb3QyLmFsbC5iUzEkdHJhaXQsIGxldmVscyA9IGMoImxuQ1ZSIiwgImxuVlIiLCAibG5SUiIpKQoKbWV0YS5wbG90Mi5hbGwuY1MxIDwtIG1ldGEucGxvdDIuYWxsLmJTMSAlPiUKICBncm91cF9ieV9hdCh2YXJzKHRyYWl0LCBHcm91cGluZ1Rlcm0pKSAlPiUKICBzdW1tYXJpc2UoCiAgICBtYWxlYmlhcyA9IHN1bSh2YWx1ZSA+IDApLCBmZW1hbGViaWFzID0gc3VtKHZhbHVlIDw9IDApLCB0b3RhbCA9IG1hbGViaWFzICsgZmVtYWxlYmlhcywKICAgIG1hbGVwZXJjZW50ID0gbWFsZWJpYXMgKiAxMDAgLyB0b3RhbCwgZmVtYWxlcGVyY2VudCA9IGZlbWFsZWJpYXMgKiAxMDAgLyB0b3RhbAogICkKCm1ldGEucGxvdDIuYWxsLmNTMSRsYWJlbCA8LSAiQWxsIHRyYWl0cyIKCiMgcmVzdHJ1Y3R1cmUgdG8gY3JlYXRlIHN0YWNrZWQgYmFyIHBsb3RzCgptZXRhLnBsb3QyLmFsbC5kUzEgPC0gYXMuZGF0YS5mcmFtZShtZXRhLnBsb3QyLmFsbC5jUzEpCm1ldGEucGxvdDIuYWxsLmVTMSA8LSBnYXRoZXIobWV0YS5wbG90Mi5hbGwuZFMxLCBrZXkgPSBzZXgsIHZhbHVlID0gcGVyY2VudCwgbWFsZXBlcmNlbnQ6ZmVtYWxlcGVyY2VudCwgZmFjdG9yX2tleSA9IFRSVUUpCgojIGNyZWF0ZSBuZXcgc2FtcGxlIHNpemUgdmFyaWFibGUKCm1ldGEucGxvdDIuYWxsLmVTMSRzYW1wbGVzaXplIDwtIHdpdGgobWV0YS5wbG90Mi5hbGwuZVMxLCBpZmVsc2Uoc2V4ID09ICJtYWxlcGVyY2VudCIsIG1hbGViaWFzLCBmZW1hbGViaWFzKSkKCm1hbGViaWFzX0ZpZ1MxX2FsbHRyYWl0cyA8LQogIGdncGxvdChtZXRhLnBsb3QyLmFsbC5lUzEpICsKICBhZXMoeCA9IEdyb3VwaW5nVGVybSwgeSA9IHBlcmNlbnQsIGZpbGwgPSBzZXgpICsKICBnZW9tX2NvbCgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA1MCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JheTQwIikgKwogIGdlb21fdGV4dCgKICAgIGRhdGEgPSBzdWJzZXQobWV0YS5wbG90Mi5hbGwuZVMxLCBzYW1wbGVzaXplICE9IDApLCBhZXMobGFiZWwgPSBzYW1wbGVzaXplKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSwKICAgIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDMuNQogICkgKwogIGZhY2V0X2dyaWQoCiAgICBjb2xzID0gdmFycyh0cmFpdCksIHJvd3MgPSB2YXJzKGxhYmVsKSwgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDE4KSwKICAgIHNjYWxlcyA9ICJmcmVlIiwgc3BhY2UgPSAiZnJlZSIKICApICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTgpICsKICB0aGVtZSgKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgc2l6ZSA9IDEwLCBtYXJnaW4gPSBtYXJnaW4odCA9IDE1LCByID0gMTUsIGIgPSAxNSwgbCA9IDE1KSksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTlVMTCwgbGluZXR5cGUgPSAiYmxhbmsiLCBmaWxsID0gImdyYXk5MCIpLAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMC41LCAibGluZXMiKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZSgpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3VyID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3IgPSAiZ3JheTk1IiksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkKICApICsKICBjb29yZF9mbGlwKCkKCiMgbWFsZWJpYXNfRmlnUzFfYWxsdHJhaXRzICAgICAjKHBhbmVsIEEgaW4gRmlndXJlIFMxKQpgYGAKCiMjIyAgT3ZlcmFsbCByZXN1bHRzIG9mIHNlY29uZCBvcmRlciBtZXRhIGFuYWx5c2lzLCBJTkNMVURJTkcgVlIKIyMjIyBSZXN0cnVjdHVyZSBkYXRhIGZvciBwbG90dGluZyAKUmVzdHJ1Y3R1cmUgTUFMRSBkYXRhIGZvciBwbG90dGluZyAKCmBgYHtyfQpvdmVyYWxsMy5tYWxlLnNpZ1MgPC0gZ2F0aGVyKG92ZXJhbGwubWFsZS5wbG90MywgcGFyYW1ldGVyLCB2YWx1ZSwgYyhsbkNWUiwgbG5WUiwgbG5SUiksIGZhY3Rvcl9rZXkgPSBUUlVFKQoKbG5DVlIuY2kgPC0gb3ZlcmFsbDMubWFsZS5zaWdTICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuQ1ZSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuQ1ZSX2xvd2VyLCBjaS5oaWdoID0gbG5DVlJfdXBwZXIpCmxuVlIuY2kgPC0gb3ZlcmFsbDMubWFsZS5zaWdTICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuVlIiKSAlPiUKICBtdXRhdGUoY2kubG93ID0gbG5WUl9sb3dlciwgY2kuaGlnaCA9IGxuVlJfdXBwZXIpCmxuUlIuY2kgPC0gb3ZlcmFsbDMubWFsZS5zaWdTICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuUlIiKSAlPiUKICBtdXRhdGUoY2kubG93ID0gbG5SUl9sb3dlciwgY2kuaGlnaCA9IGxuUlJfdXBwZXIpCgpvdmVyYWxsNC5tYWxlLnNpZ1MgPC0gYmluZF9yb3dzKGxuQ1ZSLmNpLCBsblZSLmNpLCBsblJSLmNpKSAlPiUgc2VsZWN0KEdyb3VwaW5nVGVybSwgcGFyYW1ldGVyLCB2YWx1ZSwgY2kubG93LCBjaS5oaWdoKQoKb3ZlcmFsbDQubWFsZS5zaWdTJGxhYmVsIDwtICJDSSBub3Qgb3ZlcmxhcHBpbmcgemVybyIKCiMgRGF0YSBhcmUgcmVzdHJ1Y3R1cmVkLCBhbmQgZ3JvdXBpbmcgdGVybXMgYXJlIGJlaW5nIHJlLW9yZGVyZWQKCm92ZXJhbGwzUyA8LSBnYXRoZXIob3ZlcmFsbDIsIHBhcmFtZXRlciwgdmFsdWUsIGMobG5DVlIsIGxuVlIsIGxuUlIpLCBmYWN0b3Jfa2V5ID0gVFJVRSkKCmxuQ1ZSLmNpIDwtIG92ZXJhbGwzUyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJsbkNWUiIpICU+JQogIG11dGF0ZShjaS5sb3cgPSBsbkNWUl9sb3dlciwgY2kuaGlnaCA9IGxuQ1ZSX3VwcGVyKQpsblZSLmNpIDwtIG92ZXJhbGwzUyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJsblZSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuVlJfbG93ZXIsIGNpLmhpZ2ggPSBsblZSX3VwcGVyKQpsblJSLmNpIDwtIG92ZXJhbGwzUyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJsblJSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuUlJfbG93ZXIsIGNpLmhpZ2ggPSBsblJSX3VwcGVyKQoKb3ZlcmFsbDRTIDwtIGJpbmRfcm93cyhsbkNWUi5jaSwgbG5WUi5jaSwgbG5SUi5jaSkgJT4lIHNlbGVjdChHcm91cGluZ1Rlcm0sIHBhcmFtZXRlciwgdmFsdWUsIGNpLmxvdywgY2kuaGlnaCkKCiMgcmUtb3JkZXIgR3JvdXBpbmcgVGVybXMKCm92ZXJhbGw0UyRHcm91cGluZ1Rlcm0gPC0gZmFjdG9yKG92ZXJhbGw0UyRHcm91cGluZ1Rlcm0sIGxldmVscyA9IGMoIkJlaGF2aW91ciIsICJNb3JwaG9sb2d5IiwgIk1ldGFib2xpc20iLCAiUGh5c2lvbG9neSIsICJJbW11bm9sb2d5IiwgIkhlbWF0b2xvZ3kiLCAiSGVhcnQiLCAiSGVhcmluZyIsICJFeWUiLCAiQWxsIikpCm92ZXJhbGw0UyRHcm91cGluZ1Rlcm0gPC0gZmFjdG9yKG92ZXJhbGw0UyRHcm91cGluZ1Rlcm0sIHJldihsZXZlbHMob3ZlcmFsbDRTJEdyb3VwaW5nVGVybSkpKQpvdmVyYWxsNFMkbGFiZWwgPC0gIkFsbCB0cmFpdHMiCmBgYAoKIyMjIyBQcmVwYXJhdGlvbiBmb3IgcGxvdCwgaW5jbHVkaW5nIGxuVlIKUHJlcGFyYXRpb246IFN1Yi1QbG90ICBmb3IgRmlndXJlIFMxOiBhbGwgdHJhaXRzIChTMSBCKQoKYGBge3J9Ck1ldGFtZXRhX0ZpZ1MxX2FsbHRyYWl0cyA8LSBvdmVyYWxsNFMgJT4lCgogIGdncGxvdChhZXMoeSA9IEdyb3VwaW5nVGVybSwgeCA9IHZhbHVlKSkgKwogIGdlb21fZXJyb3JiYXJoKGFlcygKICAgIHhtaW4gPSBjaS5sb3csCiAgICB4bWF4ID0gY2kuaGlnaAogICksCiAgaGVpZ2h0ID0gMC4xLCBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBwYXJhbWV0ZXIpLAogICAgZmlsbCA9ICJibGFjayIsCiAgICBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyLjIsCiAgICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgc2NhbGVfeF9jb250aW51b3VzKAogICAgbGltaXRzID0gYygtMC4yNCwgMC4yNSksCiAgICBicmVha3MgPSBjKC0wLjIsIC0wLjEsIDAsIDAuMSwgMC4yKSwKICAgIG5hbWUgPSAiRWZmZWN0IHNpemUiCiAgKSArCiAgZ2VvbV92bGluZSgKICAgIHhpbnRlcmNlcHQgPSAwLAogICAgY29sb3IgPSAiYmxhY2siLAogICAgbGluZXR5cGUgPSAiZGFzaGVkIgogICkgKwogIGZhY2V0X2dyaWQoCiAgICBjb2xzID0gdmFycyhwYXJhbWV0ZXIpLCByb3dzID0gdmFycyhsYWJlbCksCiAgICBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMjMpLAogICAgc2NhbGVzID0gImZyZWUiLAogICAgc3BhY2UgPSAiZnJlZSIKICApICsKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgc2l6ZSA9IDEwLCBtYXJnaW4gPSBtYXJnaW4odCA9IDE1LCByID0gMTUsIGIgPSAxNSwgbCA9IDE1KSksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTlVMTCwgbGluZXR5cGUgPSAiYmxhbmsiLCBmaWxsID0gImdyYXk5MCIpLAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMC41LCAibGluZXMiKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZSgpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3VyID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3IgPSAiZ3JheTk1IiksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNCksCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkKICApCgojIE1ldGFtZXRhX0ZpZ1MxX2FsbHRyYWl0cwpgYGAKCiMjIyBIZXRlcm9nZW5laXR5ClRoZSBhbmFseXNpcyBmb3IgaGV0ZXJvZ2VuZWl0eSBmb2xsb3dzIHRoZSB3b3JrZmxvdyBvZiB0aGUgYWJvdmUgc3RlcHMgZm9yIHRoZSBkaWZmZXJlbnQgbWV0YS1hbmFseXNlcy4gSG93ZXZlciwgaW4gdGhlIGluaXRpYWwgbWV0YS1hbmFseXNpcyB3ZSBleHRyYWN0IHNpZ21hXjIgYW5kIGVycm9ycyBmb3IgbW91c2Ugc3RyYWlucyBhbmQgY2VudGVycyAoSW5zdGl0dXRpb25zKS4gCgpgYGB7cn0KcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmcgPC0gYXMuZGF0YS5mcmFtZShjYmluZChjKDE6biksIG1hdHJpeChyZXAoMCwgbiAqIDMwKSwgbmNvbCA9IDMwKSkpCm5hbWVzKHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nKSA8LSBjKAogICJpZCIsICJzaWdtYTJfc3RyYWluLkNWUiIsICJzaWdtYTJfY2VudGVyLkNWUiIsICJzaWdtYTJfZXJyb3IuQ1ZSIiwgInMubmxldmVscy5zdHJhaW4uQ1ZSIiwKICAicy5ubGV2ZWxzLmNlbnRlci5DVlIiLCAicy5ubGV2ZWxzLmVycm9yLkNWUiIsICJzaWdtYTJfc3RyYWluLlZSIiwgInNpZ21hMl9jZW50ZXIuVlIiLCAic2lnbWEyX2Vycm9yLlZSIiwgInMubmxldmVscy5zdHJhaW4uVlIiLAogICJzLm5sZXZlbHMuY2VudGVyLlZSIiwgInMubmxldmVscy5lcnJvci5WUiIsICJzaWdtYTJfc3RyYWluLlJSIiwgInNpZ21hMl9jZW50ZXIuUlIiLCAic2lnbWEyX2Vycm9yLlJSIiwgInMubmxldmVscy5zdHJhaW4uUlIiLAogICJzLm5sZXZlbHMuY2VudGVyLlJSIiwgInMubmxldmVscy5lcnJvci5SUiIsICJsbkNWUiIsICJsbkNWUl9sb3dlciIsICJsbkNWUl91cHBlciIsICJsbkNWUl9zZSIsICJsblZSIiwgImxuVlJfbG93ZXIiLCAibG5WUl91cHBlciIsCiAgImxuVlJfc2UiLCAibG5SUiIsICJsblJSX2xvd2VyIiwgImxuUlJfdXBwZXIiLCAibG5SUl9zZSIKKQpgYGAKCkxPT1AKUGFyYW1ldGVycyB0byBleHRyYWN0IGZyb20gbWV0YWZvciAoc2lnbWEyJ3MsIHMubmxldmVscykKCmBgYHtyfQoKZm9yICh0IGluIDE6bikgewogIHRyeUNhdGNoKAogICAgewogICAgICBkYXRhX3Bhcl9hZ2UgPC0gZGF0YV9zdWJzZXRfcGFyYW1ldGVyaWRfaW5kaXZpZHVhbF9ieV9hZ2UoZGF0YSwgdCwgYWdlX21pbiA9IDAsIGFnZV9jZW50ZXIgPSAxMDApCgogICAgICBwb3B1bGF0aW9uX3N0YXRzIDwtIGNhbGN1bGF0ZV9wb3B1bGF0aW9uX3N0YXRzKGRhdGFfcGFyX2FnZSkKCiAgICAgIHJlc3VsdHMgPC0gY3JlYXRlX21ldGFfYW5hbHlzaXNfZWZmZWN0X3NpemVzKHBvcHVsYXRpb25fc3RhdHMpCgogICAgICAjIGxuQ1ZSLCBsb2dhcml0bSBvZiB0aGUgcmF0aW8gb2YgbWFsZSBhbmQgZmVtYWxlIGNvZWZmaWNpZW50cyBvZiB2YXJpYW5jZQoKICAgICAgY3ZyLiA8LSBtZXRhZm9yOjpybWEubXYoeWkgPSBlZmZlY3Rfc2l6ZV9DVlIsIFYgPSBzYW1wbGVfdmFyaWFuY2VfQ1ZSLCByYW5kb20gPSBsaXN0KAogICAgICAgIH4gMSB8IHN0cmFpbl9uYW1lLCB+IDEgfCBwcm9kdWN0aW9uX2NlbnRlciwKICAgICAgICB+IDEgfCBlcnIKICAgICAgKSwgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgZGF0YSA9IHJlc3VsdHMpCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDJdIDwtIGN2ci4kc2lnbWEyWzFdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDNdIDwtIGN2ci4kc2lnbWEyWzJdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDRdIDwtIGN2ci4kc2lnbWEyWzNdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDVdIDwtIGN2ci4kcy5ubGV2ZWxzWzFdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDZdIDwtIGN2ci4kcy5ubGV2ZWxzWzJdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDddIDwtIGN2ci4kcy5ubGV2ZWxzWzNdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDIwXSA8LSBjdnIuJGIKICAgICAgcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmdbdCwgMjFdIDwtIGN2ci4kY2kubGIKICAgICAgcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmdbdCwgMjJdIDwtIGN2ci4kY2kudWIKICAgICAgcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmdbdCwgMjNdIDwtIGN2ci4kc2UKCiAgICAgICMgbG5WUiwgbWFsZSB0byBmZW1hbGUgdmFyaWFiaWxpdHkgcmF0aW8gKGxvZ2FyaXRobSBvZiBtYWxlIGFuZCBmZW1hbGUgc3RhbmRhcmQgZGV2aWF0aW9ucykKCiAgICAgIHZyLiA8LSBtZXRhZm9yOjpybWEubXYoeWkgPSBlZmZlY3Rfc2l6ZV9WUiwgViA9IHNhbXBsZV92YXJpYW5jZV9WUiwgcmFuZG9tID0gbGlzdCgKICAgICAgICB+IDEgfCBzdHJhaW5fbmFtZSwgfiAxIHwgcHJvZHVjdGlvbl9jZW50ZXIsCiAgICAgICAgfiAxIHwgZXJyCiAgICAgICksIGNvbnRyb2wgPSBsaXN0KG9wdGltaXplciA9ICJvcHRpbSIsIG9wdG1ldGhvZCA9ICJOZWxkZXItTWVhZCIsIG1heGl0ID0gMTAwMCksIGRhdGEgPSByZXN1bHRzKQogICAgICByZXN1bHRzLmFsbGhldGVyby5ncm91cGluZ1t0LCA4XSA8LSB2ci4kc2lnbWEyWzFdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDldIDwtIHZyLiRzaWdtYTJbMl0KICAgICAgcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmdbdCwgMTBdIDwtIHZyLiRzaWdtYTJbM10KICAgICAgcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmdbdCwgMTFdIDwtIHZyLiRzLm5sZXZlbHNbMV0KICAgICAgcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmdbdCwgMTJdIDwtIHZyLiRzLm5sZXZlbHNbMl0KICAgICAgcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmdbdCwgMTNdIDwtIHZyLiRzLm5sZXZlbHNbM10KICAgICAgcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmdbdCwgMjRdIDwtIHZyLiRiCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDI1XSA8LSB2ci4kY2kubGIKICAgICAgcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmdbdCwgMjZdIDwtIHZyLiRjaS51YgogICAgICByZXN1bHRzLmFsbGhldGVyby5ncm91cGluZ1t0LCAyN10gPC0gdnIuJHNlCgogICAgICAjIGxuUlIsIHJlc3BvbnNlIHJhdGlvIChsb2dhcml0aG0gb2YgbWFsZSBhbmQgZmVtYWxlIG1lYW5zKQoKICAgICAgcnIuIDwtIG1ldGFmb3I6OnJtYS5tdih5aSA9IGVmZmVjdF9zaXplX1JSLCBWID0gc2FtcGxlX3ZhcmlhbmNlX1JSLCByYW5kb20gPSBsaXN0KAogICAgICAgIH4gMSB8IHN0cmFpbl9uYW1lLCB+IDEgfCBwcm9kdWN0aW9uX2NlbnRlciwKICAgICAgICB+IDEgfCBlcnIKICAgICAgKSwgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgZGF0YSA9IHJlc3VsdHMpCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDE0XSA8LSByci4kc2lnbWEyWzFdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDE1XSA8LSByci4kc2lnbWEyWzJdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDE2XSA8LSByci4kc2lnbWEyWzNdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDE3XSA8LSByci4kcy5ubGV2ZWxzWzFdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDE4XSA8LSByci4kcy5ubGV2ZWxzWzJdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDE5XSA8LSByci4kcy5ubGV2ZWxzWzNdCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDI4XSA8LSByci4kYgogICAgICByZXN1bHRzLmFsbGhldGVyby5ncm91cGluZ1t0LCAyOV0gPC0gcnIuJGNpLmxiCiAgICAgIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3QsIDMwXSA8LSByci4kY2kudWIKICAgICAgcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmdbdCwgMzFdIDwtIHJyLiRzZQogICAgfSwKICAgIGVycm9yID0gZnVuY3Rpb24oZSkgewogICAgICBjYXQoIkVSUk9SIDoiLCBjb25kaXRpb25NZXNzYWdlKGUpLCAiXG4iKQogICAgfQogICkKfQpgYGAKCiMjIyMgRXhjbHVkZSB0cmFpdHMsIG1lcmdlIGRhdGFzZXRzCgpgYGB7cn0KcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmcyIDwtIHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nW3Jlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nJHMubmxldmVscy5zdHJhaW4uVlIgIT0gMCwgXQojIG5yb3cocmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmcyKSAjMjE4ICBTWiAyMjM/Pz8KYGBgCgpNZXJnZSBkYXRhIHNldHMgY29udGFpbmluZyBtZXRhZm9yIHJlc3VsdHMgd2l0aCBwcm9jZWR1cmUgZXRjLiBuYW1lcyAKCmBgYHtyfQojIHByb2NlZHVyZXMgPC0gcmVhZC5jc3YoaGVyZSgiZXhwb3J0IiwgInByb2NlZHVyZXMuY3N2IikpCgpyZXN1bHRzLmFsbGhldGVyby5ncm91cGluZzIkcGFyYW1ldGVyX2dyb3VwIDwtIGRhdGEkcGFyYW1ldGVyX2dyb3VwW21hdGNoKHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nMiRpZCwgZGF0YSRpZCldCnJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nMiRwcm9jZWR1cmUgPC0gZGF0YSRwcm9jZWR1cmVfbmFtZVttYXRjaChyZXN1bHRzLmFsbGhldGVyby5ncm91cGluZzIkaWQsIGRhdGEkaWQpXQoKcmVzdWx0cy5hbGxoZXRlcm8uZ3JvdXBpbmcyJEdyb3VwaW5nVGVybSA8LSBwcm9jZWR1cmVzJEdyb3VwaW5nVGVybVttYXRjaChyZXN1bHRzLmFsbGhldGVyby5ncm91cGluZzIkcHJvY2VkdXJlLCBwcm9jZWR1cmVzJHByb2NlZHVyZSldCnJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nMiRwYXJhbWV0ZXJfbmFtZSA8LSBkYXRhJHBhcmFtZXRlcl9uYW1lW21hdGNoKHJlc3VsdHMuYWxsaGV0ZXJvLmdyb3VwaW5nMiRpZCwgZGF0YSRpZCldCmBgYAoKIyMjIyBDb3JyZWxhdGVkIHBhcmFtZXRlcnMKIyNGRUxJWCA6IGNoZWNrPyBudW1iZXJzIGRvbid0IGFkZCB1cD8/CmBgYHtyfQptZXRhaGV0ZXJvMSA8LSByZXN1bHRzLmFsbGhldGVyby5ncm91cGluZzIKIyBsZW5ndGgodW5pcXVlKG1ldGFoZXRlcm8xJHByb2NlZHVyZSkpICMxOCAgU1ogMTkKIyBsZW5ndGgodW5pcXVlKG1ldGFoZXRlcm8xJEdyb3VwaW5nVGVybSkpICM5IFN6IG9rCiMgbGVuZ3RoKHVuaXF1ZShtZXRhaGV0ZXJvMSRwYXJhbWV0ZXJfZ3JvdXApKSAjIDE0OSBTWiAxNTIKIyBsZW5ndGgodW5pcXVlKG1ldGFoZXRlcm8xJHBhcmFtZXRlcl9uYW1lKSkgIzIxOCAgU1ogMjIzCgojIENvdW50IG9mIG51bWJlciBvZiBwYXJhbWV0ZXIgbmFtZXMgKGNvcnJlbGF0ZWQgc3ViLXRyYWl0cykgaW4gZWFjaCBwYXJhbWV0ZXIgZ3JvdXAgKHBhcl9ncm91cF9zaXplKQoKbWV0YWhldGVybzFiIDwtCiAgbWV0YWhldGVybzEgJT4lCiAgZ3JvdXBfYnkocGFyYW1ldGVyX2dyb3VwKSAlPiUKICBtdXRhdGUocGFyX2dyb3VwX3NpemUgPSBuX2Rpc3RpbmN0KHBhcmFtZXRlcl9uYW1lKSkKCm1ldGFoZXRlcm8xJHBhcl9ncm91cF9zaXplIDwtIG1ldGFoZXRlcm8xYiRwYXJfZ3JvdXBfc2l6ZVttYXRjaChtZXRhaGV0ZXJvMSRwYXJhbWV0ZXJfZ3JvdXAsIG1ldGFoZXRlcm8xYiRwYXJhbWV0ZXJfZ3JvdXApXQoKIyBDcmVhdGUgc3Vic2V0cyB3aXRoID4gMSBjb3VudCAocGFyX2dyb3VwX3NpemUgPiAxKQoKbWV0YWhldGVybzFfc3ViIDwtIHN1YnNldChtZXRhaGV0ZXJvMSwgcGFyX2dyb3VwX3NpemUgPiAxKSAjIDkwIG9ic2VydmF0aW9ucwojIHN0cihtZXRhaGV0ZXJvMV9zdWIpCiMgbWV0YWhldGVybzFfc3ViJHNhbXBsZVNpemUgPC0gYXMubnVtZXJpYyhtZXRhaGV0ZXJvMV9zdWIkc2FtcGxlU2l6ZSkgI2Zyb20gcHJldmlvdXMgYW5hbHlzaXM/IGRvbid0IHRoaW5rIGlzIHVzZWQ6IDogZGVsZXRlIGluIGZpbmFsIHZlcnNpb24KCiMgTmVzdCBkYXRhCgpuX2NvdW50LiA8LSBtZXRhaGV0ZXJvMV9zdWIgJT4lCiAgZ3JvdXBfYnkocGFyYW1ldGVyX2dyb3VwKSAlPiUKICAjIG11dGF0ZShyYXdfTiA9IHN1bShzYW1wbGVTaXplKSkgJT4lICAjZG9uJ3QgdGhpbmsgaXMgbmVjZXNzYXJ5OiBkZWxldGUgaW4gZmluYWwgdmVyc2lvbgogIG5lc3QoKQoKIyBtZXRhLWFuYWx5c2lzIHByZXBhcmF0aW9uCgptb2RlbF9jb3VudC4gPC0gbl9jb3VudC4gJT4lCiAgbXV0YXRlKAogICAgbW9kZWxfbG5SUiA9IG1hcChkYXRhLCB+IHJvYnUoLngkbG5SUiB+IDEsCiAgICAgIGRhdGEgPSAueCwgc3R1ZHludW0gPSAueCRpZCwgbW9kZWx3ZWlnaHRzID0gYygiQ09SUiIpLCByaG8gPSAwLjgsCiAgICAgIHNtYWxsID0gVFJVRSwgdmFyLmVmZi5zaXplID0gKC54JGxuUlJfc2UpXjIKICAgICkpLAogICAgbW9kZWxfbG5WUiA9IG1hcChkYXRhLCB+IHJvYnUoLngkbG5WUiB+IDEsCiAgICAgIGRhdGEgPSAueCwgc3R1ZHludW0gPSAueCRpZCwgbW9kZWx3ZWlnaHRzID0gYygiQ09SUiIpLCByaG8gPSAwLjgsCiAgICAgIHNtYWxsID0gVFJVRSwgdmFyLmVmZi5zaXplID0gKC54JGxuVlJfc2UpXjIKICAgICkpLAogICAgbW9kZWxfbG5DVlIgPSBtYXAoZGF0YSwgfiByb2J1KC54JGxuQ1ZSIH4gMSwKICAgICAgZGF0YSA9IC54LCBzdHVkeW51bSA9IC54JGlkLCBtb2RlbHdlaWdodHMgPSBjKCJDT1JSIiksIHJobyA9IDAuOCwKICAgICAgc21hbGwgPSBUUlVFLCB2YXIuZWZmLnNpemUgPSAoLngkbG5DVlJfc2UpXjIKICAgICkpCiAgKQoKCiMgUm9idW1ldGEgb2JqZWN0IGRldGFpbHM6CiMgc3RyKG1vZGVsX2NvdW50LiRtb2RlbF9sbkNWUltbMV1dKQoKIyMgKlBlcmZvcm0gbWV0YS1hbmFseXNlcyBvbiBjb3JyZWxhdGVkIHN1Yi10cmFpdHMsIHVzaW5nIHJvYnVtZXRhCiAjIFN1c2kgLyBGRUxJWDogd2hhdCdzIHRoaXMgYmVsb3c/CiMgU2hpbmljaGk6IFdlIHRoaW5rIHdlIHdhbnQgdG8gdXNlIHRoZXNlIGZvciBmdXJ0aGVyIGFuYWx5c2VzOgojIHJlc2lkdWFsIHZhcmlhbmNlOiBhcy5udW1lcmljKHJvYnVfZml0JG1vZF9pbmZvJHRlcm0xKSAgICAgKHNhbWUgYXMgJ21vZF9pbmZvJHRhdS5zcScpCiMgc2FtcGxlIHNpemU6IHJvYnVfZml0JE4KCiMjICoqRXh0cmFjdCBhbmQgc2F2ZSBwYXJhbWV0ZXIgZXN0aW1hdGVzCgojIEZlbGl4OiBkb2Vzbid0IHdvcmsgLCBlcnJvciBtZXNzYWdlOgojISEhISEhISEhISEgRVJST1IhISEhISEhISEhISEhISEhISEhIQojRXJyb3I6IENvbHVtbiBgcGFyYW1ldGVyX2dyb3VwYCBjYW4ndCBiZSBtb2RpZmllZCBiZWNhdXNlIGl0J3MgYSBncm91cGluZyB2YXJpYWJsZQoKY291bnRfZnVuLiA8LSBmdW5jdGlvbihtb2Rfc3ViKSB7CiAgcmV0dXJuKGMoYXMubnVtZXJpYyhtb2Rfc3ViJG1vZF9pbmZvJHRlcm0xKSwgbW9kX3N1YiROKSkKfQoKcm9idXN1Yl9SUi4gPC0gbW9kZWxfY291bnQuICU+JQogIHRyYW5zbXV0ZShwYXJhbWV0ZXJfZ3JvdXAsIGVzdGltYXRlbG5SUiA9IG1hcChtb2RlbF9sblJSLCBjb3VudF9mdW4uKSkgJT4lCiAgbXV0YXRlKHIgPSBtYXAoZXN0aW1hdGVsblJSLCB+IGRhdGEuZnJhbWUodCguKSkpKSAlPiUKICB1bm5lc3QocikgJT4lCiAgc2VsZWN0KC1lc3RpbWF0ZWxuUlIpICU+JQogIHB1cnJyOjpzZXRfbmFtZXMoYygicGFyYW1ldGVyX2dyb3VwIiwgInZhci5SUiIsICJOLlJSIikpCgpyb2J1c3ViX0NWUi4gPC0gbW9kZWxfY291bnQuICU+JQogIHRyYW5zbXV0ZShwYXJhbWV0ZXJfZ3JvdXAsIGVzdGltYXRlbG5DVlIgPSBtYXAobW9kZWxfbG5DVlIsIGNvdW50X2Z1bi4pKSAlPiUKICBtdXRhdGUociA9IG1hcChlc3RpbWF0ZWxuQ1ZSLCB+IGRhdGEuZnJhbWUodCguKSkpKSAlPiUKICB1bm5lc3QocikgJT4lCiAgc2VsZWN0KC1lc3RpbWF0ZWxuQ1ZSKSAlPiUKICBwdXJycjo6c2V0X25hbWVzKGMoInBhcmFtZXRlcl9ncm91cCIsICJ2YXIuQ1ZSIiwgIk4uQ1ZSIikpCgpyb2J1c3ViX1ZSLiA8LSBtb2RlbF9jb3VudC4gJT4lCiAgdHJhbnNtdXRlKHBhcmFtZXRlcl9ncm91cCwgZXN0aW1hdGVsblZSID0gbWFwKG1vZGVsX2xuVlIsIGNvdW50X2Z1bi4pKSAlPiUKICBtdXRhdGUociA9IG1hcChlc3RpbWF0ZWxuVlIsIH4gZGF0YS5mcmFtZSh0KC4pKSkpICU+JQogIHVubmVzdChyKSAlPiUKICBzZWxlY3QoLWVzdGltYXRlbG5WUikgJT4lCiAgcHVycnI6OnNldF9uYW1lcyhjKCJwYXJhbWV0ZXJfZ3JvdXAiLCAidmFyLlZSIiwgIk4uVlIiKSkKCnJvYnVfYWxsLiA8LSBmdWxsX2pvaW4ocm9idXN1Yl9DVlIuLCByb2J1c3ViX1ZSLikgJT4lIGZ1bGxfam9pbiguLCByb2J1c3ViX1JSLikKYGBgCgpNZXJnZSB0aGUgdHdvIGRhdGEgc2V0cyAodGhlIG5ldyBbcm9idV9hbGwuXSBhbmQgdGhlIGluaXRpYWwgW3VuY29ycmVsYXRlZCBzdWItdHJhaXRzIHdpdGggY291bnQgPSAxXSkKCkluIHRoaXMgc3RlcCwgd2UgCQoxKSBtZXJnZSB0aGUgTiBmcm9tIHJvYnVtZXRhIGFuZCB0aGUgIE4gZnJvbSBtZXRhZm9yIChzLm5sZXZlbHMuZXJyb3IpIHRvZ2V0aGVyIGludG8gdGhlIHNhbWUgY29sdW1ucyAoTi5SUiwgTi5WUiwgTi5DVlIpCjIpIGNhbGN1bGF0ZSB0aGUgdG90YWwgdmFyaWFuY2UgZm9yIG1ldGFmb3IgbW9kZWxzIGFzIHRoZSBzdW0gb2YgcmFuZG9tIGVmZmVjdCB2YXJpYW5jZXMgYW5kIHRoZSByZXNpZHVhbCBlcnJvciwgdGhlbiBhZGQgaW4gdGhlIHNhbWUgY29sdW1ucyB0b2dldGhlciB3aXRoIHRoZSByZXNpZHVhbCB2YXJpYW5jZXMgZnJvbSByb2J1bWV0YQoKYGBge3J9Cm1ldGFoZXRlcm9fYWxsIDwtIG1ldGFoZXRlcm8xICU+JQogIGZpbHRlcihwYXJfZ3JvdXBfc2l6ZSA9PSAxKSAlPiUKICBhc190aWJibGUoKQptZXRhaGV0ZXJvX2FsbCROLlJSIDwtIG1ldGFoZXRlcm9fYWxsJHMubmxldmVscy5lcnJvci5SUgptZXRhaGV0ZXJvX2FsbCROLkNWUiA8LSBtZXRhaGV0ZXJvX2FsbCRzLm5sZXZlbHMuZXJyb3IuQ1ZSCm1ldGFoZXRlcm9fYWxsJE4uVlIgPC0gbWV0YWhldGVyb19hbGwkcy5ubGV2ZWxzLmVycm9yLlZSCm1ldGFoZXRlcm9fYWxsJHZhci5SUiA8LSBsb2coc3FydChtZXRhaGV0ZXJvX2FsbCRzaWdtYTJfc3RyYWluLlJSICsgbWV0YWhldGVyb19hbGwkc2lnbWEyX2NlbnRlci5SUiArIG1ldGFoZXRlcm9fYWxsJHNpZ21hMl9lcnJvci5SUikpCm1ldGFoZXRlcm9fYWxsJHZhci5WUiA8LSBsb2coc3FydChtZXRhaGV0ZXJvX2FsbCRzaWdtYTJfc3RyYWluLlZSICsgbWV0YWhldGVyb19hbGwkc2lnbWEyX2NlbnRlci5WUiArIG1ldGFoZXRlcm9fYWxsJHNpZ21hMl9lcnJvci5WUikpCm1ldGFoZXRlcm9fYWxsJHZhci5DVlIgPC0gbG9nKHNxcnQobWV0YWhldGVyb19hbGwkc2lnbWEyX3N0cmFpbi5DVlIgKyBtZXRhaGV0ZXJvX2FsbCRzaWdtYTJfY2VudGVyLkNWUiArIG1ldGFoZXRlcm9fYWxsJHNpZ21hMl9lcnJvci5DVlIpKQojIHN0cihtZXRhaGV0ZXJvX2FsbCkKIyBzdHIocm9idV9hbGwuKQoKbWV0YWhldGVyb19hbGwgPC0gbWV0YWhldGVyb19hbGwgJT4lIG11dGF0ZSgKICB2YXIuUlIgPSBpZl9lbHNlKHZhci5SUiA9PSAtSW5mLCAtNywgdmFyLlJSKSwKICB2YXIuVlIgPSBpZl9lbHNlKHZhci5WUiA9PSAtSW5mLCAtNSwgdmFyLlZSKSwKICB2YXIuQ1ZSID0gaWZfZWxzZSh2YXIuQ1ZSID09IC1JbmYsIC02LCB2YXIuQ1ZSKQopCgojICoqQ29tYmluZSBkYXRhCiMjIFN0ZXAxCmNvbWJpbmVkbWV0YWhldGVybyA8LSBiaW5kX3Jvd3Mocm9idV9hbGwuLCBtZXRhaGV0ZXJvX2FsbCkKIyBnbGltcHNlKGNvbWJpbmVkbWV0YWhldGVybykKCiMgU3RlcHMgMiYzCgptZXRhY29tYm9oZXRlcm8gPC0gY29tYmluZWRtZXRhaGV0ZXJvCm1ldGFjb21ib2hldGVybyRjb3VudHMgPC0gbWV0YWhldGVybzEkcGFyX2dyb3VwX3NpemVbbWF0Y2gobWV0YWNvbWJvaGV0ZXJvJHBhcmFtZXRlcl9ncm91cCwgbWV0YWhldGVybzEkcGFyYW1ldGVyX2dyb3VwKV0KbWV0YWNvbWJvaGV0ZXJvJHByb2NlZHVyZTIgPC0gbWV0YWhldGVybzEkcHJvY2VkdXJlW21hdGNoKG1ldGFjb21ib2hldGVybyRwYXJhbWV0ZXJfZ3JvdXAsIG1ldGFoZXRlcm8xJHBhcmFtZXRlcl9ncm91cCldCm1ldGFjb21ib2hldGVybyRHcm91cGluZ1Rlcm0yIDwtIG1ldGFoZXRlcm8xJEdyb3VwaW5nVGVybVttYXRjaChtZXRhY29tYm9oZXRlcm8kcGFyYW1ldGVyX2dyb3VwLCBtZXRhaGV0ZXJvMSRwYXJhbWV0ZXJfZ3JvdXApXQoKIyAqKkNsZWFuLXVwIGFuZCByZW5hbWUKCm1ldGFjb21ib2hldGVybyA8LSBtZXRhY29tYm9oZXRlcm9bLCBjKDE6NywgNDM6NDUpXQpuYW1lcyhtZXRhY29tYm9oZXRlcm8pWzldIDwtICJwcm9jZWR1cmUiCm5hbWVzKG1ldGFjb21ib2hldGVybylbMTBdIDwtICJHcm91cGluZ1Rlcm0iCmBgYAoKIyMjIyBNZXRhLWFuYWx5c2lzIG9mIGhldGVyb2dlbmVpdHkKCmBgYHtyfQojIyBQZXJmb3JtIG1ldGEtbWV0YS1hbmFseXNpcyAoMyBmb3IgZWFjaCBvZiB0aGUgOSBncm91cGluZyB0ZXJtczogdmFyLkNWUiwgdmFyLlZSLCB2YXIuUlIpCgptZXRhY29tYm9oZXRlcm9fZmluYWwgPC0gbWV0YWNvbWJvaGV0ZXJvICU+JQogIGdyb3VwX2J5KEdyb3VwaW5nVGVybSkgJT4lCiAgbmVzdCgpCgojIEZpbmFsIGZpeGVkIGVmZmVjdHMgbWV0YS1hbmFseXNlcyB3aXRoaW4gZ3JvdXBpbmcgdGVybXMsIHdpdGggU0Ugb2YgdGhlIGVzdGltYXRlCgojIG1ldGFjb21ib2hldGVybyR2YXIuQ1ZSCgpoZXRlcm9nMSA8LSBtZXRhY29tYm9oZXRlcm9fZmluYWwgJT4lCgogIG11dGF0ZSgKICAgIG1vZGVsX2hldGVyb0NWUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICAgIHlpID0gLngkdmFyLkNWUiwgc2VpID0gc3FydCgxIC8gMiAqICgueCROLkNWUiAtIDEpKSwKICAgICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwMCwgc3RlcGFkaiA9IDAuNSksIHZlcmJvc2UgPSBGCiAgICApKSwKICAgIG1vZGVsX2hldGVyb1ZSID0gbWFwKGRhdGEsIH4gbWV0YWZvcjo6cm1hLnVuaSgKICAgICAgeWkgPSAueCR2YXIuVlIsIHNlaSA9IHNxcnQoMSAvIDIgKiAoLngkTi5WUiAtIDEpKSwKICAgICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwMCwgc3RlcGFkaiA9IDAuNSksIHZlcmJvc2UgPSBGCiAgICApKSwKICAgIG1vZGVsX2hldGVyb1JSID0gbWFwKGRhdGEsIH4gbWV0YWZvcjo6cm1hLnVuaSgKICAgICAgeWkgPSAueCR2YXIuUlIsIHNlaSA9IHNxcnQoMSAvIDIgKiAoLngkTi5SUiAtIDEpKSwKICAgICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwMCwgc3RlcGFkaiA9IDAuNSksIHZlcmJvc2UgPSBGCiAgICApKQogICkKCgojIFJlLXN0cnVjdHVyZSBkYXRhIGZvciBlYWNoIGdyb3VwaW5nIHRlcm07IGV4dHJhY3QgaGV0ZXJvZ2VuZW5pdHkvdmFyaWFuY2UgdGVybXM7IGRlbGV0ZSB1bi11c2VkIHZhcmlhYmxlcwojIyBGRUxJWDogQUREICJBTEwiCkJlaGF2aW91ci4gPC0gaGV0ZXJvZzEgJT4lCiAgZmlsdGVyKC4sIEdyb3VwaW5nVGVybSA9PSAiQmVoYXZpb3VyIikgJT4lCiAgc2VsZWN0KC4sIC1kYXRhKSAlPiUKICBtdXRhdGUoCiAgICBoZXRlcm9DVlIgPSAuW1syXV1bWzFdXSRiLCBoZXRlcm9DVlJfbG93ZXIgPSAuW1syXV1bWzFdXSRjaS5sYiwgaGV0ZXJvQ1ZSX3VwcGVyID0gLltbMl1dW1sxXV0kY2kudWIsIGhldGVyb0NWUl9zZSA9IC5bWzJdXVtbMV1dJHNlLAogICAgaGV0ZXJvVlIgPSAuW1szXV1bWzFdXSRiLCBoZXRlcm9WUl9sb3dlciA9IC5bWzNdXVtbMV1dJGNpLmxiLCBoZXRlcm9WUl91cHBlciA9IC5bWzNdXVtbMV1dJGNpLnViLCBoZXRlcm9WUl9zZSA9IC5bWzNdXVtbMV1dJHNlLAogICAgaGV0ZXJvUlIgPSAuW1s0XV1bWzFdXSRiLCBoZXRlcm9SUl9sb3dlciA9IC5bWzRdXVtbMV1dJGNpLmxiLCBoZXRlcm9SUl91cHBlciA9IC5bWzRdXVtbMV1dJGNpLnViLCBoZXRlcm9SUl9zZSA9IC5bWzRdXVtbMV1dJHNlCiAgKSAlPiUKICBzZWxlY3QoLiwgR3JvdXBpbmdUZXJtLCBoZXRlcm9DVlI6aGV0ZXJvUlJfc2UpCgpJbW11bm9sb2d5LiA8LSBoZXRlcm9nMSAlPiUKICBmaWx0ZXIoLiwgR3JvdXBpbmdUZXJtID09ICJJbW11bm9sb2d5IikgJT4lCiAgc2VsZWN0KC4sIC1kYXRhKSAlPiUKICBtdXRhdGUoCiAgICBoZXRlcm9DVlIgPSAuW1syXV1bWzFdXSRiLCBoZXRlcm9DVlJfbG93ZXIgPSAuW1syXV1bWzFdXSRjaS5sYiwgaGV0ZXJvQ1ZSX3VwcGVyID0gLltbMl1dW1sxXV0kY2kudWIsIGhldGVyb0NWUl9zZSA9IC5bWzJdXVtbMV1dJHNlLAogICAgaGV0ZXJvVlIgPSAuW1szXV1bWzFdXSRiLCBoZXRlcm9WUl9sb3dlciA9IC5bWzNdXVtbMV1dJGNpLmxiLCBoZXRlcm9WUl91cHBlciA9IC5bWzNdXVtbMV1dJGNpLnViLCBoZXRlcm9WUl9zZSA9IC5bWzNdXVtbMV1dJHNlLAogICAgaGV0ZXJvUlIgPSAuW1s0XV1bWzFdXSRiLCBoZXRlcm9SUl9sb3dlciA9IC5bWzRdXVtbMV1dJGNpLmxiLCBoZXRlcm9SUl91cHBlciA9IC5bWzRdXVtbMV1dJGNpLnViLCBoZXRlcm9SUl9zZSA9IC5bWzRdXVtbMV1dJHNlCiAgKSAlPiUKICBzZWxlY3QoLiwgR3JvdXBpbmdUZXJtLCBoZXRlcm9DVlI6aGV0ZXJvUlJfc2UpCgoKSGVtYXRvbG9neS4gPC0gaGV0ZXJvZzEgJT4lCiAgZmlsdGVyKC4sIEdyb3VwaW5nVGVybSA9PSAiSGVtYXRvbG9neSIpICU+JQogIHNlbGVjdCguLCAtZGF0YSkgJT4lCiAgbXV0YXRlKAogICAgaGV0ZXJvQ1ZSID0gLltbMl1dW1sxXV0kYiwgaGV0ZXJvQ1ZSX2xvd2VyID0gLltbMl1dW1sxXV0kY2kubGIsIGhldGVyb0NWUl91cHBlciA9IC5bWzJdXVtbMV1dJGNpLnViLCBoZXRlcm9DVlJfc2UgPSAuW1syXV1bWzFdXSRzZSwKICAgIGhldGVyb1ZSID0gLltbM11dW1sxXV0kYiwgaGV0ZXJvVlJfbG93ZXIgPSAuW1szXV1bWzFdXSRjaS5sYiwgaGV0ZXJvVlJfdXBwZXIgPSAuW1szXV1bWzFdXSRjaS51YiwgaGV0ZXJvVlJfc2UgPSAuW1szXV1bWzFdXSRzZSwKICAgIGhldGVyb1JSID0gLltbNF1dW1sxXV0kYiwgaGV0ZXJvUlJfbG93ZXIgPSAuW1s0XV1bWzFdXSRjaS5sYiwgaGV0ZXJvUlJfdXBwZXIgPSAuW1s0XV1bWzFdXSRjaS51YiwgaGV0ZXJvUlJfc2UgPSAuW1s0XV1bWzFdXSRzZQogICkgJT4lCiAgc2VsZWN0KC4sIEdyb3VwaW5nVGVybSwgaGV0ZXJvQ1ZSOmhldGVyb1JSX3NlKQoKCkhlYXJpbmcuIDwtIGhldGVyb2cxICU+JQogIGZpbHRlciguLCBHcm91cGluZ1Rlcm0gPT0gIkhlYXJpbmciKSAlPiUKICBzZWxlY3QoLiwgLWRhdGEpICU+JQogIG11dGF0ZSgKICAgIGhldGVyb0NWUiA9IC5bWzJdXVtbMV1dJGIsIGhldGVyb0NWUl9sb3dlciA9IC5bWzJdXVtbMV1dJGNpLmxiLCBoZXRlcm9DVlJfdXBwZXIgPSAuW1syXV1bWzFdXSRjaS51YiwgaGV0ZXJvQ1ZSX3NlID0gLltbMl1dW1sxXV0kc2UsCiAgICBoZXRlcm9WUiA9IC5bWzNdXVtbMV1dJGIsIGhldGVyb1ZSX2xvd2VyID0gLltbM11dW1sxXV0kY2kubGIsIGhldGVyb1ZSX3VwcGVyID0gLltbM11dW1sxXV0kY2kudWIsIGhldGVyb1ZSX3NlID0gLltbM11dW1sxXV0kc2UsCiAgICBoZXRlcm9SUiA9IC5bWzRdXVtbMV1dJGIsIGhldGVyb1JSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGhldGVyb1JSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGhldGVyb1JSX3NlID0gLltbNF1dW1sxXV0kc2UKICApICU+JQogIHNlbGVjdCguLCBHcm91cGluZ1Rlcm0sIGhldGVyb0NWUjpoZXRlcm9SUl9zZSkKClBoeXNpb2xvZ3kuIDwtIGhldGVyb2cxICU+JQogIGZpbHRlciguLCBHcm91cGluZ1Rlcm0gPT0gIlBoeXNpb2xvZ3kiKSAlPiUKICBzZWxlY3QoLiwgLWRhdGEpICU+JQogIG11dGF0ZSgKICAgIGhldGVyb0NWUiA9IC5bWzJdXVtbMV1dJGIsIGhldGVyb0NWUl9sb3dlciA9IC5bWzJdXVtbMV1dJGNpLmxiLCBoZXRlcm9DVlJfdXBwZXIgPSAuW1syXV1bWzFdXSRjaS51YiwgaGV0ZXJvQ1ZSX3NlID0gLltbMl1dW1sxXV0kc2UsCiAgICBoZXRlcm9WUiA9IC5bWzNdXVtbMV1dJGIsIGhldGVyb1ZSX2xvd2VyID0gLltbM11dW1sxXV0kY2kubGIsIGhldGVyb1ZSX3VwcGVyID0gLltbM11dW1sxXV0kY2kudWIsIGhldGVyb1ZSX3NlID0gLltbM11dW1sxXV0kc2UsCiAgICBoZXRlcm9SUiA9IC5bWzRdXVtbMV1dJGIsIGhldGVyb1JSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGhldGVyb1JSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGhldGVyb1JSX3NlID0gLltbNF1dW1sxXV0kc2UKICApICU+JQogIHNlbGVjdCguLCBHcm91cGluZ1Rlcm0sIGhldGVyb0NWUjpoZXRlcm9SUl9zZSkKCk1ldGFib2xpc20uIDwtIGhldGVyb2cxICU+JQogIGZpbHRlciguLCBHcm91cGluZ1Rlcm0gPT0gIk1ldGFib2xpc20iKSAlPiUKICBzZWxlY3QoLiwgLWRhdGEpICU+JQogIG11dGF0ZSgKICAgIGhldGVyb0NWUiA9IC5bWzJdXVtbMV1dJGIsIGhldGVyb0NWUl9sb3dlciA9IC5bWzJdXVtbMV1dJGNpLmxiLCBoZXRlcm9DVlJfdXBwZXIgPSAuW1syXV1bWzFdXSRjaS51YiwgaGV0ZXJvQ1ZSX3NlID0gLltbMl1dW1sxXV0kc2UsCiAgICBoZXRlcm9WUiA9IC5bWzNdXVtbMV1dJGIsIGhldGVyb1ZSX2xvd2VyID0gLltbM11dW1sxXV0kY2kubGIsIGhldGVyb1ZSX3VwcGVyID0gLltbM11dW1sxXV0kY2kudWIsIGhldGVyb1ZSX3NlID0gLltbM11dW1sxXV0kc2UsCiAgICBoZXRlcm9SUiA9IC5bWzRdXVtbMV1dJGIsIGhldGVyb1JSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGhldGVyb1JSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGhldGVyb1JSX3NlID0gLltbNF1dW1sxXV0kc2UKICApICU+JQogIHNlbGVjdCguLCBHcm91cGluZ1Rlcm0sIGhldGVyb0NWUjpoZXRlcm9SUl9zZSkKCk1vcnBob2xvZ3kuIDwtIGhldGVyb2cxICU+JQogIGZpbHRlciguLCBHcm91cGluZ1Rlcm0gPT0gIk1vcnBob2xvZ3kiKSAlPiUKICBzZWxlY3QoLiwgLWRhdGEpICU+JQogIG11dGF0ZSgKICAgIGhldGVyb0NWUiA9IC5bWzJdXVtbMV1dJGIsIGhldGVyb0NWUl9sb3dlciA9IC5bWzJdXVtbMV1dJGNpLmxiLCBoZXRlcm9DVlJfdXBwZXIgPSAuW1syXV1bWzFdXSRjaS51YiwgaGV0ZXJvQ1ZSX3NlID0gLltbMl1dW1sxXV0kc2UsCiAgICBoZXRlcm9WUiA9IC5bWzNdXVtbMV1dJGIsIGhldGVyb1ZSX2xvd2VyID0gLltbM11dW1sxXV0kY2kubGIsIGhldGVyb1ZSX3VwcGVyID0gLltbM11dW1sxXV0kY2kudWIsIGhldGVyb1ZSX3NlID0gLltbM11dW1sxXV0kc2UsCiAgICBoZXRlcm9SUiA9IC5bWzRdXVtbMV1dJGIsIGhldGVyb1JSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGhldGVyb1JSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGhldGVyb1JSX3NlID0gLltbNF1dW1sxXV0kc2UKICApICU+JQogIHNlbGVjdCguLCBHcm91cGluZ1Rlcm0sIGhldGVyb0NWUjpoZXRlcm9SUl9zZSkKCkhlYXJ0LiA8LSBoZXRlcm9nMSAlPiUKICBmaWx0ZXIoLiwgR3JvdXBpbmdUZXJtID09ICJIZWFydCIpICU+JQogIHNlbGVjdCguLCAtZGF0YSkgJT4lCiAgbXV0YXRlKAogICAgaGV0ZXJvQ1ZSID0gLltbMl1dW1sxXV0kYiwgaGV0ZXJvQ1ZSX2xvd2VyID0gLltbMl1dW1sxXV0kY2kubGIsIGhldGVyb0NWUl91cHBlciA9IC5bWzJdXVtbMV1dJGNpLnViLCBoZXRlcm9DVlJfc2UgPSAuW1syXV1bWzFdXSRzZSwKICAgIGhldGVyb1ZSID0gLltbM11dW1sxXV0kYiwgaGV0ZXJvVlJfbG93ZXIgPSAuW1szXV1bWzFdXSRjaS5sYiwgaGV0ZXJvVlJfdXBwZXIgPSAuW1szXV1bWzFdXSRjaS51YiwgaGV0ZXJvVlJfc2UgPSAuW1szXV1bWzFdXSRzZSwKICAgIGhldGVyb1JSID0gLltbNF1dW1sxXV0kYiwgaGV0ZXJvUlJfbG93ZXIgPSAuW1s0XV1bWzFdXSRjaS5sYiwgaGV0ZXJvUlJfdXBwZXIgPSAuW1s0XV1bWzFdXSRjaS51YiwgaGV0ZXJvUlJfc2UgPSAuW1s0XV1bWzFdXSRzZQogICkgJT4lCiAgc2VsZWN0KC4sIEdyb3VwaW5nVGVybSwgaGV0ZXJvQ1ZSOmhldGVyb1JSX3NlKQoKRXllLiA8LSBoZXRlcm9nMSAlPiUKICBmaWx0ZXIoLiwgR3JvdXBpbmdUZXJtID09ICJFeWUiKSAlPiUKICBzZWxlY3QoLiwgLWRhdGEpICU+JQogIG11dGF0ZSgKICAgIGhldGVyb0NWUiA9IC5bWzJdXVtbMV1dJGIsIGhldGVyb0NWUl9sb3dlciA9IC5bWzJdXVtbMV1dJGNpLmxiLCBoZXRlcm9DVlJfdXBwZXIgPSAuW1syXV1bWzFdXSRjaS51YiwgaGV0ZXJvQ1ZSX3NlID0gLltbMl1dW1sxXV0kc2UsCiAgICBoZXRlcm9WUiA9IC5bWzNdXVtbMV1dJGIsIGhldGVyb1ZSX2xvd2VyID0gLltbM11dW1sxXV0kY2kubGIsIGhldGVyb1ZSX3VwcGVyID0gLltbM11dW1sxXV0kY2kudWIsIGhldGVyb1ZSX3NlID0gLltbM11dW1sxXV0kc2UsCiAgICBoZXRlcm9SUiA9IC5bWzRdXVtbMV1dJGIsIGhldGVyb1JSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGhldGVyb1JSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGhldGVyb1JSX3NlID0gLltbNF1dW1sxXV0kc2UKICApICU+JQogIHNlbGVjdCguLCBHcm91cGluZ1Rlcm0sIGhldGVyb0NWUjpoZXRlcm9SUl9zZSkKCiAjRkVMSVg6IGNoZWNrLkkgaGF2ZSBhZGRlZCAvIG1vZGlmaWUgdGhpcyBjYW4ndCBydW4gdG8gY2hlY2sKQWxsLiA8LSBhcy5kYXRhLmZyYW1lKGhldGVyb2cxICU+JSAKICAgICAgbXV0YXRlKAogICBoZXRlcm9DVlIgPSAuW1syXV1bWzFdXSRiLCBoZXRlcm9DVlJfbG93ZXIgPSAuW1syXV1bWzFdXSRjaS5sYiwgaGV0ZXJvQ1ZSX3VwcGVyID0gLltbMl1dW1sxXV0kY2kudWIsIGhldGVyb0NWUl9zZSA9IC5bWzJdXVtbMV1dJHNlLCBoZWVyb1ZSID0gLltbM11dW1sxXV0kYiwgaGV0ZXJvVlJfbG93ZXIgPSAuW1szXV1bWzFdXSRjaS5sYiwgaGV0ZXJvVlJfdXBwZXIgPSAuW1szXV1bWzFdXSRjaS51YiwgaGV0ZXJvVlJfc2UgPSAuW1szXV1bWzFdXSRzZSwKICBoZXRlcm9SUiA9IC5bWzRdXVtbMV1dJGIsIGhldGVyb1JSX2xvd2VyID0gLltbNF1dW1sxXV0kY2kubGIsIGhldGVyb1JSX3VwcGVyID0gLltbNF1dW1sxXV0kY2kudWIsIGhldGVyb1JSX3NlID0gLltbNF1dW1sxXV0kc2UKKSlbLCBjKDU6MTYpXQoKQWxsLiRoZXRlcm9DVlIgPC0gYXMubnVtZXJpYyhBbGwuJGhldGVyb0NWUikKQWxsLiRoZXRlcm9WUiA8LSBhcy5udW1lcmljKEFsbC4kaGV0ZXJvVlIpCkFsbC4kaGV0ZXJvUlIgPC0gYXMubnVtZXJpYyhBbGwuJGxoZXRlcm9SUikKQWxsLiA8LSBBbGwuICU+JSBtdXRhdGUoR3JvdXBpbmdUZXJtID0gIkFsbCIpCgpoZXRlcm9nMiA8LSBiaW5kX3Jvd3MoQmVoYXZpb3VyLiwgTW9ycGhvbG9neS4sIE1ldGFib2xpc20uLCBQaHlzaW9sb2d5LiwgSW1tdW5vbG9neS4sIEhlbWF0b2xvZ3kuLCBIZWFydC4sIEhlYXJpbmcuLCBFeWUuLCBBbGwuKQojIHN0cihoZXRlcm9nMikKYGBgCgojIyMjIEhldGVyb2dlbmVpdHkgUExPVApSZXN0cnVjdHVyZSBkYXRhIGZvciBwbG90dGluZyAKCmBgYHtyfQpoZXRlcm9nMyA8LSBnYXRoZXIoaGV0ZXJvZzIsIHBhcmFtZXRlciwgdmFsdWUsIGMoaGV0ZXJvQ1ZSLCBoZXRlcm9WUiwgaGV0ZXJvUlIpLCBmYWN0b3Jfa2V5ID0gVFJVRSkKCmhldGVyb0NWUi5jaSA8LSBoZXRlcm9nMyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJoZXRlcm9DVlIiKSAlPiUKICBtdXRhdGUoY2kubG93ID0gaGV0ZXJvQ1ZSX2xvd2VyLCBjaS5oaWdoID0gaGV0ZXJvQ1ZSX3VwcGVyKQpoZXRlcm9WUi5jaSA8LSBoZXRlcm9nMyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJoZXRlcm9WUiIpICU+JQogIG11dGF0ZShjaS5sb3cgPSBoZXRlcm9WUl9sb3dlciwgY2kuaGlnaCA9IGhldGVyb1ZSX3VwcGVyKQpoZXRlcm9SUi5jaSA8LSBoZXRlcm9nMyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJoZXRlcm9SUiIpICU+JQogIG11dGF0ZShjaS5sb3cgPSBoZXRlcm9SUl9sb3dlciwgY2kuaGlnaCA9IGhldGVyb1JSX3VwcGVyKQoKaGV0ZXJvZzQgPC0gYmluZF9yb3dzKGhldGVyb0NWUi5jaSwgaGV0ZXJvVlIuY2ksIGhldGVyb1JSLmNpKSAlPiUgc2VsZWN0KEdyb3VwaW5nVGVybSwgcGFyYW1ldGVyLCB2YWx1ZSwgY2kubG93LCBjaS5oaWdoKQoKIyAqKlJlLW9yZGVyIGdyb3VwaW5nIHRlcm1zCgpoZXRlcm9nNCRHcm91cGluZ1Rlcm0gPC0gZmFjdG9yKGhldGVyb2c0JEdyb3VwaW5nVGVybSwgbGV2ZWxzID0gYygiQmVoYXZpb3VyIiwgIk1vcnBob2xvZ3kiLCAiTWV0YWJvbGlzbSIsICJQaHlzaW9sb2d5IiwgIkltbXVub2xvZ3kiLCAiSGVtYXRvbG9neSIsICJIZWFydCIsICJIZWFyaW5nIiwgIkV5ZSIpKQpoZXRlcm9nNCRHcm91cGluZ1Rlcm0gPC0gZmFjdG9yKGhldGVyb2c0JEdyb3VwaW5nVGVybSwgcmV2KGxldmVscyhoZXRlcm9nNCRHcm91cGluZ1Rlcm0pKSkKaGV0ZXJvZzQkbGFiZWwgPC0gIkFsbCB0cmFpdHMiCiMgd3JpdGUuY3N2KGhldGVyb2c0LCAiaGV0ZXJvZzQuY3N2IikKYGBgCgojIyMjIFBsb3QgUzEgQyAoU2Vjb25kLW9yZGVyIG1ldGEgYW5hbHlzaXMgb24gaGV0ZXJvZ2VuZWl0eSkKCmBgYHtyfQpoZXRlcm9nNSA8LSBoZXRlcm9nNApoZXRlcm9nNSRtZWFuIDwtIGFzLm51bWVyaWMoZXhwKGhldGVyb2c1JHZhbHVlKSkKaGV0ZXJvZzUkY2kubCA8LSBhcy5udW1lcmljKGV4cChoZXRlcm9nNSRjaS5sb3cpKQpoZXRlcm9nNSRjaS5oIDwtIGFzLm51bWVyaWMoZXhwKGhldGVyb2c1JGNpLmhpZ2gpKQoKaGV0ZXJvZzYgPC0gaGV0ZXJvZzUKCkhldGVyb1MxIDwtCiAgaGV0ZXJvZzYgJT4lCiAgZmlsdGVyKAogICAgcGFyYW1ldGVyID09ICJoZXRlcm9DVlIiIHwgcGFyYW1ldGVyID09ICJoZXRlcm9SUiIKICApICU+JSAgIyMgRkVMSVggOiBkbyB3ZSBuZWVkIHRoaXMgImZpbHRlciIgLSB3ZSB3YW50IFZSIGFzIHdlbGw/PwogIGdncGxvdChhZXMoeSA9IEdyb3VwaW5nVGVybSwgeCA9IG1lYW4pKSArCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKAogICAgeG1pbiA9IGNpLmwsCiAgICB4bWF4ID0gY2kuaAogICksCiAgaGVpZ2h0ID0gMC4xLCBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBwYXJhbWV0ZXIpLAogICAgZmlsbCA9ICJibGFjayIsCiAgICBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyLjIsCiAgICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgc2NhbGVfeF9jb250aW51b3VzKAogICAgbGltaXRzID0gYygtMC4xLCAxLjQpLAogICAgIyBicmVha3MgPSBjKDAsIDAuMSwgMC4yKSwKICAgIG5hbWUgPSAic2lnbWFeMiIKICApICsKICAjIGdlb21fdmxpbmUoeGludGVyY2VwdD0wLAogICMgY29sb3I9J2JsYWNrJywKICAjIGxpbmV0eXBlPSdkYXNoZWQnKSsKICBmYWNldF9ncmlkKAogICAgY29scyA9IHZhcnMocGFyYW1ldGVyKSwgcm93cyA9IHZhcnMobGFiZWwpLAogICAgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDIzKSwKICAgIHNjYWxlcyA9ICJmcmVlIiwKICAgIHNwYWNlID0gImZyZWUiCiAgKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoCiAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNzAsIHNpemUgPSAxMCwgbWFyZ2luID0gbWFyZ2luKHQgPSAxNSwgciA9IDE1LCBiID0gMTUsIGwgPSAxNSkpLAogICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5VTEwsIGxpbmV0eXBlID0gImJsYW5rIiwgZmlsbCA9ICJncmF5OTAiKSwKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDAuNSwgImxpbmVzIiksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG91ciA9ICJncmF5OTUiKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG9yID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTQpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpCiAgKQoKIyBIZXRlcm9TMQoKYGBgCgoKIyMjIyBDb21iaW5lZCBGaWd1cmUgUzE6IG92ZXJhbGwgQ291bnQgZGF0YSwgTWV0YSBhbmx5c2lzIHJlc3VsdHMsIEhldGVyb2dlbmVpdHkpCgpgYGB7cn0KRmlnUzEgPC0gZ2dhcnJhbmdlKG1hbGViaWFzX0ZpZ1MxX2FsbHRyYWl0cyArIHhsYWIoInBlcmNlbnRhZ2Ugc2V4IGJpYXMiKSwgTWV0YW1ldGFfRmlnUzFfYWxsdHJhaXRzLCBIZXRlcm9TMSwgbnJvdyA9IDMsIGFsaWduID0gInYiLCBoZWlnaHRzID0gYygxLCAxLCAxKSwgbGFiZWxzID0gYygiQSIsICJCIiwgIkMiKSkKRmlnUzEKIyBnZ3NhdmUoIkZpZ1MxX092ZXJhbGxSZXN1bHRzLnBkZiIsIHBsb3QgPSBGaWc0LCB3aWR0aCA9IDYsIGhlaWdodCA9IDUpCmBgYAoKIyMgRmlndXJlIFMyCgpQbG90IEZpZ1MyIGFsbCBzaWduaWZpY2FudCByZXN1bHRzIChDSSBub3Qgb3ZlcmxhcHBpbmcgemVybykgZm9yIG1hbGVzCiMjIyBGRUxJWDogICJBTEwiIG1pc3NpbmcuIApgYGB7cn0KbWV0YS5wbG90Mi5zaWcuYlMgPC0gbWV0YS5wbG90Mi5zaWdbLCBjKCJsbkNWUiIsICJsblZSIiwgImxuUlIiLCAibG5DVlJzaWciLCAibG5WUnNpZyIsICJsblJSc2lnIiwgIkdyb3VwaW5nVGVybSIpXQoKbWV0YS5wbG90Mi5zaWcuY1MgPC0gZ2F0aGVyKG1ldGEucGxvdDIuc2lnLmJTLCB0cmFpdCwgdmFsdWUsIGxuQ1ZSOmxuUlIpCm1ldGEucGxvdDIuc2lnLmNTJHNpZyA8LSAicGxhY2Vob2xkZXIiCgptZXRhLnBsb3QyLnNpZy5jUyR0cmFpdCA8LSBmYWN0b3IobWV0YS5wbG90Mi5zaWcuY1MkdHJhaXQsIGxldmVscyA9IGMoImxuQ1ZSIiwgImxuVlIiLCAibG5SUiIpKQoKbWV0YS5wbG90Mi5zaWcuY1Mkc2lnIDwtIGlmZWxzZShtZXRhLnBsb3QyLnNpZy5jUyR0cmFpdCA9PSAibG5DVlIiLCBtZXRhLnBsb3QyLnNpZy5jUyRsbkNWUnNpZywKICBpZmVsc2UobWV0YS5wbG90Mi5zaWcuY1MkdHJhaXQgPT0gImxuVlIiLCBtZXRhLnBsb3QyLnNpZy5jUyRsblZSc2lnLCBtZXRhLnBsb3QyLnNpZy5jUyRsblJSc2lnKQopCgojIGNob29zaW5nIHNleCBiaWFzZWQgbG4tcmF0aW9zIHNpZ25pZmljYW50bHkgbGFyZ2VyIHRoYW4gMAptZXRhLnBsb3RTMi5zaWcubWFsZWJpYXMgPC0gbWV0YS5wbG90Mi5zaWcuY1MgJT4lCiAgZ3JvdXBfYnlfYXQodmFycyh0cmFpdCwgR3JvdXBpbmdUZXJtKSkgJT4lCiAgZmlsdGVyKHNpZyA9PSAxKSAlPiUKICBzdW1tYXJpc2UobWFsZV9zaWcgPSBzdW0odmFsdWUgPiAwKSwgZmVtYWxlX3NpZyA9IHN1bSh2YWx1ZSA8IDApLCB0b3RhbCA9IG1hbGVfc2lnICsgZmVtYWxlX3NpZykKCm1ldGEucGxvdFMyLnNpZy5tYWxlYmlhcyA8LSB1bmdyb3VwKG1ldGEucGxvdFMyLnNpZy5tYWxlYmlhcykgJT4lCiAgYWRkX3Jvdyh0cmFpdCA9ICJsbkNWUiIsIEdyb3VwaW5nVGVybSA9ICJIZWFyaW5nIiwgbWFsZV9zaWcgPSAwLCBmZW1hbGVfc2lnID0gMCwgLmJlZm9yZSA9IDQpICU+JSAjIGFkZCAiSGVhcmluZyIgZm9yIGxuQ1ZSIChub3QgZmlsdGVyZWQgYXMgb25seSB6ZXJvcykKICBtdXRhdGUobWFsZXBlcmNlbnQgPSBtYWxlX3NpZyAqIDEwMCAvIHRvdGFsLCBmZW1hbGVwZXJjZW50ID0gZmVtYWxlX3NpZyAqIDEwMCAvIHRvdGFsKQoKbWV0YS5wbG90UzIuc2lnLm1hbGViaWFzJGxhYmVsIDwtICJDSSBub3Qgb3ZlcmxhcHBpbmcgemVybyIKCiMgcmVzdHJ1Y3R1cmUgdG8gY3JlYXRlIHN0YWNrZWQgYmFyIHBsb3RzCgptZXRhLnBsb3RTMi5zaWcuYm90aHNleGVzIDwtIGFzLmRhdGEuZnJhbWUobWV0YS5wbG90UzIuc2lnLm1hbGViaWFzKQptZXRhLnBsb3RTMi5zaWcuYm90aHNleGVzLmIgPC0gZ2F0aGVyKG1ldGEucGxvdFMyLnNpZy5ib3Roc2V4ZXMsIGtleSA9IHNleCwgdmFsdWUgPSBwZXJjZW50LCBtYWxlcGVyY2VudDpmZW1hbGVwZXJjZW50LCBmYWN0b3Jfa2V5ID0gVFJVRSkKCiMgY3JlYXRlIG5ldyBzYW1wbGUgc2l6ZSB2YXJpYWJsZQoKbWV0YS5wbG90UzIuc2lnLmJvdGhzZXhlcy5iJHNhbXBsZXNpemUgPC0gd2l0aChtZXRhLnBsb3RTMi5zaWcuYm90aHNleGVzLmIsIGlmZWxzZShzZXggPT0gIm1hbGVwZXJjZW50IiwgbWFsZV9zaWcsIGZlbWFsZV9zaWcpKQoKIyAqUGxvdCBGaWcyIGFsbCBzaWduaWZpY2FudCByZXN1bHRzIChDSSBub3Qgb3ZlcmxhcHBpbmcgemVybyk6CiMgICAgIG5vIHNpZy4gbG5DVlIgZm9yICdIZWFyaW5nJyBpbiBlaXRoZXIgc2V4OyBubyBzaWcuIG1hbGUtYmlhc2VkIGxuQ1ZSIGZvciAnSW1tdW5vbG9neScgYW5kICdFeWUsIGFuZCBubyBzaWcuIG1hbGUtYmlhc2VkIGxuVlIgZm9yICdFeWUnCgoKbWFsZWJpYXNfRmlnUzJfc2lndHJhaXRzIDwtCiAgZ2dwbG90KG1ldGEucGxvdFMyLnNpZy5ib3Roc2V4ZXMuYikgKwogIGFlcyh4ID0gR3JvdXBpbmdUZXJtLCB5ID0gcGVyY2VudCwgZmlsbCA9IHNleCkgKwogIGdlb21fY29sKCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5NDAiKSArCiAgZ2VvbV90ZXh0KAogICAgZGF0YSA9IHN1YnNldChtZXRhLnBsb3RTMi5zaWcuYm90aHNleGVzLmIsIHNhbXBsZXNpemUgIT0gMCksIGFlcyhsYWJlbCA9IHNhbXBsZXNpemUpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gLjUpLAogICAgY29sb3IgPSAid2hpdGUiLCBzaXplID0gMy41CiAgKSArCiAgZmFjZXRfZ3JpZCgKICAgIGNvbHMgPSB2YXJzKHRyYWl0KSwgcm93cyA9IHZhcnMobGFiZWwpLCBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMTgpLAogICAgc2NhbGVzID0gImZyZWUiLCBzcGFjZSA9ICJmcmVlIgogICkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxOCkgKwogIHRoZW1lKAogICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjcwLCBzaXplID0gMTAsIG1hcmdpbiA9IG1hcmdpbih0ID0gMTUsIHIgPSAxNSwgYiA9IDE1LCBsID0gMTUpKSwKICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSBOVUxMLCBsaW5ldHlwZSA9ICJibGFuayIsIGZpbGwgPSAiZ3JheTkwIiksCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgwLjUsICJsaW5lcyIpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKCksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAic29saWQiLCBjb2xvdXIgPSAiZ3JheTk1IiksCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAic29saWQiLCBjb2xvciA9ICJncmF5OTUiKSwKICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKQogICkgKwogIGNvb3JkX2ZsaXAoKQoKIyBtYWxlYmlhc19GaWdTMl9zaWd0cmFpdHMgIyB0aGlzIGlzIEZpZ3VyZSBTMiBBCmBgYAojIyMgUHJlcGFyZSBkYXRhIGZvciB0cmFpdHMgd2l0aCBlZmZlY3Qgc2l6ZSByYXRpb3MgPiAxMCUgbGFyZ2VyIGluIG1hbGVzLCBzdXBwbGVtZW50YWwgRmlndXJlIFMyCiMjIyBGRUxJWDogICJBTEwiIG1pc3NpbmcuIApUaGlzIEZpZ3VyZSBleHRlbmRzIEZpZ3VyZSA0LCBhcyBpdCBpbmNsdWRlcyByZXN1bHRzIG5vdCBvbmx5IGZvciBsbkNWUiBhbmQgbG5SUiBidXQgYWxzbyBsbkNWUi4gSW4gYWRkaXRpb24sIHdlIGNvbXBhcmUgdHdvIGRpZmZlcmVudCBhc3Nlc3NtZW50cyBvZiBzZXgtYmlhcywgc2lnbmlmaWNhbmNlIChDSSBub3Qgb3ZlcmxhcHBpbmcgemVybykgYW5kIHNleCBkaWZmZXJlbmNlcyBpbiBtYWxlIC8gZmVtYWxlIHJhdGlvcyA+IDEwJQoKIyMjIE92ZXIgMTAlIG1hbGUgYmlhcywgY291bnQgZGF0YSAoZmlyc3QtIG9yZGVyIG1ldGFuYWx5c2lzKSAKYGBge3J9Cm1ldGEucGxvdDIub3ZlcjEwIDwtIG1ldGFfY2xlYW4gJT4lCiAgc2VsZWN0KGxuQ1ZSLCBsblZSLCBsblJSLCBHcm91cGluZ1Rlcm0pICU+JQogIGFycmFuZ2UoR3JvdXBpbmdUZXJtKSAKCm1ldGEucGxvdDIub3ZlcjEwLmIgPC0gZ2F0aGVyKG1ldGEucGxvdDIub3ZlcjEwLCB0cmFpdCwgdmFsdWUsIGMobG5DVlIsIGxuVlIsIGxuUlIpKSAKCm1ldGEucGxvdDIub3ZlcjEwLmIkdHJhaXQgPC0gZmFjdG9yKG1ldGEucGxvdDIub3ZlcjEwLmIkdHJhaXQsIGxldmVscyA9IGMoImxuQ1ZSIiwgImxuVlIiLCAibG5SUiIpKSAKCm1ldGEucGxvdDIub3ZlcjEwLmMgPC0gbWV0YS5wbG90Mi5vdmVyMTAuYiAlPiUKICBncm91cF9ieV9hdCh2YXJzKHRyYWl0LCBHcm91cGluZ1Rlcm0pKSAlPiUKICBzdW1tYXJpc2UoCiAgICBtYWxlYmlhcyA9IHN1bSh2YWx1ZSA+IGxvZygxMSAvIDEwKSksIGZlbWFsZWJpYXMgPSBzdW0odmFsdWUgPCBsb2coOSAvIDEwKSksIHRvdGFsID0gbWFsZWJpYXMgKyBmZW1hbGViaWFzLAogICAgbWFsZXBlcmNlbnQgPSBtYWxlYmlhcyAqIDEwMCAvIHRvdGFsLCBmZW1hbGVwZXJjZW50ID0gZmVtYWxlYmlhcyAqIDEwMCAvIHRvdGFsCiAgKQoKbWV0YS5wbG90Mi5vdmVyMTAuYyRsYWJlbCA8LSAiU2V4IGRpZmZlcmVuY2UgaW4gbS9mIHJhdGlvcyA+IDEwJSIKCiMgcmVzdHJ1Y3R1cmUgdG8gY3JlYXRlIHN0YWNrZWQgYmFyIHBsb3RzCgptZXRhLnBsb3QyLm92ZXIxMC5jIDwtIGFzLmRhdGEuZnJhbWUobWV0YS5wbG90Mi5vdmVyMTAuYykKbWV0YS5wbG90Mi5vdmVyMTAuZCA8LSBnYXRoZXIobWV0YS5wbG90Mi5vdmVyMTAuYywga2V5ID0gc2V4LCB2YWx1ZSA9IHBlcmNlbnQsIG1hbGVwZXJjZW50OmZlbWFsZXBlcmNlbnQsIGZhY3Rvcl9rZXkgPSBUUlVFKQoKIyBjcmVhdGUgbmV3IHNhbXBsZSBzaXplIHZhcmlhYmxlCgptZXRhLnBsb3QyLm92ZXIxMC5kJHNhbXBsZXNpemUgPC0gd2l0aChtZXRhLnBsb3QyLm92ZXIxMC5kLCBpZmVsc2Uoc2V4ID09ICJtYWxlcGVyY2VudCIsIG1hbGViaWFzLCBmZW1hbGViaWFzKSkKCiMgKlBsb3QgRmlnMiBTZXggZGlmZmVyZW5jZSBpbiBtL2YgcmF0aW8gPiAxMCUKbWFsZWJpYXNfRmlnMl9vdmVyMTAgPC0KICBnZ3Bsb3QobWV0YS5wbG90Mi5vdmVyMTAuZCkgKwogIGFlcyh4ID0gR3JvdXBpbmdUZXJtLCB5ID0gcGVyY2VudCwgZmlsbCA9IHNleCkgKwogIGdlb21fY29sKCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5NDAiKSArCiAgZ2VvbV90ZXh0KAogICAgZGF0YSA9IHN1YnNldChtZXRhLnBsb3QyLm92ZXIxMC5kLCBzYW1wbGVzaXplICE9IDApLCBhZXMobGFiZWwgPSBzYW1wbGVzaXplKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSwKICAgIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDMuNQogICkgKwogIGZhY2V0X2dyaWQoCiAgICBjb2xzID0gdmFycyh0cmFpdCksIHJvd3MgPSB2YXJzKGxhYmVsKSwgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDE4KSwKICAgIHNjYWxlcyA9ICJmcmVlIiwgc3BhY2UgPSAiZnJlZSIKICApICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTgpICsKICB0aGVtZSgKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgc2l6ZSA9IDEwLCBtYXJnaW4gPSBtYXJnaW4odCA9IDE1LCByID0gMTUsIGIgPSAxNSwgbCA9IDE1KSksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5VTEwsIGxpbmV0eXBlID0gImJsYW5rIiwgZmlsbCA9ICJncmF5OTAiKSwKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDAuNSwgImxpbmVzIiksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG91ciA9ICJncmF5OTUiKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG9yID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpCiAgKSArCiAgY29vcmRfZmxpcCgpCgojIG1hbGViaWFzX0ZpZzJfb3ZlcjEwICAoc3VwcGxlbWVudGFsIEZpZ3VyZSBTMikKYGBgCgojIyMjIEZpZyBTMiwgc2Vjb25kLW9yZGVyIG1ldGEtYW5hbHlzaXMsIG1hbGUgdHJhaXRzCiMjIyMgRmVtYWxlIEZpZ3VyZSwgc2lnbmlmaWNhbnQgdHJhaXRzCkZlbWFsZSBGaWdTMiBCIHNpZwoKUHJlcGFyZSBkYXRhIGZvciB0cmFpdHMgd2l0aCBDSSBub3Qgb3ZlcmxhcHBpbmcgMApjcmVhdGUgY29sdW1uIHdpdGggMT0gZGlmZmVyZW50IGZyb20gemVybywgMD0gemVybyBpbmNsdWRlZCBpbiBDSQoKClJlc3RydWN0dXJlIGRhdGEgZm9yIHBsb3R0aW5nCgpgYGB7cn0Kb3ZlcmFsbDMuZmVtYWxlLnNpZ1MgPC0gZ2F0aGVyKG92ZXJhbGwuZmVtYWxlLnBsb3QzLCBwYXJhbWV0ZXIsIHZhbHVlLCBjKGxuQ1ZSLCBsblZSLCBsblJSKSwgZmFjdG9yX2tleSA9IFRSVUUpCgpsbkNWUi5jaSA8LSBvdmVyYWxsMy5mZW1hbGUuc2lnUyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJsbkNWUiIpICU+JQogIG11dGF0ZShjaS5sb3cgPSBsbkNWUl9sb3dlciwgY2kuaGlnaCA9IGxuQ1ZSX3VwcGVyKQpsblZSLmNpIDwtIG92ZXJhbGwzLmZlbWFsZS5zaWdTICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuVlIiKSAlPiUKICBtdXRhdGUoY2kubG93ID0gbG5WUl9sb3dlciwgY2kuaGlnaCA9IGxuVlJfdXBwZXIpCmxuUlIuY2kgPC0gb3ZlcmFsbDMuZmVtYWxlLnNpZ1MgJT4lCiAgZmlsdGVyKHBhcmFtZXRlciA9PSAibG5SUiIpICU+JQogIG11dGF0ZShjaS5sb3cgPSBsblJSX2xvd2VyLCBjaS5oaWdoID0gbG5SUl91cHBlcikKCm92ZXJhbGw0LmZlbWFsZS5zaWdTIDwtIGJpbmRfcm93cyhsbkNWUi5jaSwgbG5WUi5jaSwgbG5SUi5jaSkgJT4lIHNlbGVjdChHcm91cGluZ1Rlcm0sIHBhcmFtZXRlciwgdmFsdWUsIGNpLmxvdywgY2kuaGlnaCkKCm92ZXJhbGw0LmZlbWFsZS5zaWdTJGxhYmVsIDwtICJDSSBub3Qgb3ZlcmxhcHBpbmcgemVybyIKCiMjCgpNZXRhbWV0YV9GaWdTMl9mZW1hbGUuc2lnIDwtIG92ZXJhbGw0LmZlbWFsZS5zaWdTICU+JQogIGdncGxvdChhZXMoeSA9IEdyb3VwaW5nVGVybSwgeCA9IHZhbHVlKSkgKwogIGdlb21fZXJyb3JiYXJoKGFlcygKICAgIHhtaW4gPSBjaS5sb3csCiAgICB4bWF4ID0gY2kuaGlnaAogICksCiAgaGVpZ2h0ID0gMC4xLCBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBwYXJhbWV0ZXIpLAogICAgZmlsbCA9ICJzYWxtb24xIiwgY29sb3IgPSAic2FsbW9uMSIsIHNpemUgPSAyLjIsCiAgICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgc2NhbGVfeF9jb250aW51b3VzKAogICAgbGltaXRzID0gYygtMC40LCAwKSwKICAgIGJyZWFrcyA9IGMoLTAuMywgMCksCiAgICBuYW1lID0gIkVmZmVjdCBzaXplIgogICkgKwogIGdlb21fdmxpbmUoCiAgICB4aW50ZXJjZXB0ID0gMCwKICAgIGNvbG9yID0gImJsYWNrIiwKICAgIGxpbmV0eXBlID0gImRhc2hlZCIKICApICsKICBmYWNldF9ncmlkKAogICAgY29scyA9IHZhcnMocGFyYW1ldGVyKSwgIyByb3dzID0gdmFycyhsYWJlbCksCiAgICAjIGxhYmVsbGVyID0gbGFiZWxfd3JhcF9nZW4od2lkdGggPSAyMyksCiAgICBzY2FsZXMgPSAiZnJlZSIsCiAgICBzcGFjZSA9ICJmcmVlIgogICkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKAogICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjcwLCBzaXplID0gMTAsIG1hcmdpbiA9IG1hcmdpbih0ID0gMTUsIHIgPSAxNSwgYiA9IDE1LCBsID0gMTUpKSwKICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSBOVUxMLCBsaW5ldHlwZSA9ICJibGFuayIsIGZpbGwgPSAiZ3JheTkwIiksCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgwLjUsICJsaW5lcyIpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKCksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAic29saWQiLCBjb2xvdXIgPSAiZ3JheTk1IiksCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAic29saWQiLCBjb2xvciA9ICJncmF5OTUiKSwKICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKQogICkKCiMgTWV0YW1ldGFfRmlnUzJfZmVtYWxlLnNpZwpgYGAKClByZXBhcmUgZGF0YSBmb3IgdHJhaXRzIHdpdGggbS9mIGRpZmZlcmVuY2UgPiAxMCUKCkNyZWF0ZSBjb2x1bW4gd2l0aCAxPSBsYXJnZXIsIDA9IGRpZmZlcmVuY2Ugbm90IGxhcmdlciB0aGFuIDEwJSBiZXR3ZWVuIG1hbGUvZmVtYWxlIHJhdGlvcwpgYGB7cn0KbWV0YS5tYWxlLnBsb3QzLnBlcmMgPC0gbWV0YWNvbWJvICU+JQogIG11dGF0ZSgKICAgIHBlcmNDVlIgPSBpZmVsc2UobG5DVlIgPiBsb2coMTEgLyAxMCksIDEsIDApLAogICAgcGVyY1ZSID0gaWZlbHNlKGxuVlIgPiBsb2coMTEgLyAxMCksIDEsIDApLAogICAgcGVyY1JSID0gaWZlbHNlKGxuUlIgPiBsb2coMTEgLyAxMCksIDEsIDApCiAgKQoKIyBTaWduaWZpY2FudCBzdWJzZXQgZm9yIGxuQ1ZSCm1ldGFjb21ib19tYWxlLnBsb3QzLkNWUi5wZXJjIDwtIG1ldGEubWFsZS5wbG90My5wZXJjICU+JQogIGZpbHRlcihwZXJjQ1ZSID09IDEpICU+JQogIGdyb3VwX2J5KEdyb3VwaW5nVGVybSkgJT4lCiAgbmVzdCgpCgptZXRhY29tYm9fbWFsZS5wbG90My5DVlIucGVyYy5hbGwgPC0gbWV0YS5tYWxlLnBsb3QzLnBlcmMgJT4lCiAgZmlsdGVyKHBlcmNDVlIgPT0gMSkgJT4lCiAgbmVzdCgpCgojIFNpZ25pZmljYW50IHN1YnNldCBmb3IgbG5WUgptZXRhY29tYm9fbWFsZS5wbG90My5WUi5wZXJjIDwtIG1ldGEubWFsZS5wbG90My5wZXJjICU+JQogIGZpbHRlcihwZXJjVlIgPT0gMSkgJT4lCiAgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBuZXN0KCkKCm1ldGFjb21ib19tYWxlLnBsb3QzLlZSLnBlcmMuYWxsIDwtIG1ldGEubWFsZS5wbG90My5wZXJjICU+JQogIGZpbHRlcihwZXJjVlIgPT0gMSkgJT4lCiAgbmVzdCgpCgojIFNpZ25pZmljYW50IHN1YnNldCBmb3IgbG5SUgptZXRhY29tYm9fbWFsZS5wbG90My5SUi5wZXJjIDwtIG1ldGEubWFsZS5wbG90My5wZXJjICU+JQogIGZpbHRlcihwZXJjUlIgPT0gMSkgJT4lCiAgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBuZXN0KCkKCm1ldGFjb21ib19tYWxlLnBsb3QzLlJSLnBlcmMuYWxsIDwtIG1ldGEubWFsZS5wbG90My5wZXJjICU+JQogIGZpbHRlcihwZXJjUlIgPT0gMSkgJT4lCiAgbmVzdCgpCgoKIyAqKkZpbmFsIGZpeGVkIGVmZmVjdHMgbWV0YS1hbmFseXNlcyB3aXRoaW4gZ3JvdXBpbmcgdGVybXMgYW5kIGFjcm9zcyBncm91cGluZyB0ZXJtcywgd2l0aCBTRSBvZiB0aGUgZXN0aW1hdGUKCnBsb3QzLm1hbGUubWV0YS5DVlIucGVyYyA8LSBtZXRhY29tYm9fbWFsZS5wbG90My5DVlIucGVyYyAlPiUKICBtdXRhdGUobW9kZWxfbG5DVlIgPSBtYXAoZGF0YSwgfiBtZXRhZm9yOjpybWEudW5pKAogICAgeWkgPSAueCRsbkNWUiwgc2VpID0gKC54JGxuQ1ZSX3VwcGVyIC0gLngkbG5DVlJfbG93ZXIpIC8gKDIgKiAxLjk2KSwKICAgIGNvbnRyb2wgPSBsaXN0KG9wdGltaXplciA9ICJvcHRpbSIsIG9wdG1ldGhvZCA9ICJOZWxkZXItTWVhZCIsIG1heGl0ID0gMTAwMCksIHZlcmJvc2UgPSBGCiAgKSkpCgpwbG90My5tYWxlLm1ldGEuVlIucGVyYyA8LSBtZXRhY29tYm9fbWFsZS5wbG90My5WUi5wZXJjICU+JQogIG11dGF0ZShtb2RlbF9sblZSID0gbWFwKGRhdGEsIH4gbWV0YWZvcjo6cm1hLnVuaSgKICAgIHlpID0gLngkbG5WUiwgc2VpID0gKC54JGxuVlJfdXBwZXIgLSAueCRsblZSX2xvd2VyKSAvICgyICogMS45NiksCiAgICBjb250cm9sID0gbGlzdChvcHRpbWl6ZXIgPSAib3B0aW0iLCBvcHRtZXRob2QgPSAiTmVsZGVyLU1lYWQiLCBtYXhpdCA9IDEwMDApLCB2ZXJib3NlID0gRgogICkpKQoKcGxvdDMubWFsZS5tZXRhLlJSLnBlcmMgPC0gbWV0YWNvbWJvX21hbGUucGxvdDMuUlIucGVyYyAlPiUKICBtdXRhdGUobW9kZWxfbG5SUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuUlIsIHNlaSA9ICgueCRsblJSX3VwcGVyIC0gLngkbG5SUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCiMgQWNyb3NzIGFsbCBncm91cGluZyB0ZXJtcyAjCgpwbG90My5tYWxlLm1ldGEuQ1ZSLnBlcmMuYWxsIDwtIG1ldGFjb21ib19tYWxlLnBsb3QzLkNWUi5wZXJjLmFsbCAlPiUKICBtdXRhdGUobW9kZWxfbG5DVlIgPSBtYXAoZGF0YSwgfiBtZXRhZm9yOjpybWEudW5pKAogICAgeWkgPSAueCRsbkNWUiwgc2VpID0gKC54JGxuQ1ZSX3VwcGVyIC0gLngkbG5DVlJfbG93ZXIpIC8gKDIgKiAxLjk2KSwKICAgIGNvbnRyb2wgPSBsaXN0KG9wdGltaXplciA9ICJvcHRpbSIsIG9wdG1ldGhvZCA9ICJOZWxkZXItTWVhZCIsIG1heGl0ID0gMTAwMCksIHZlcmJvc2UgPSBGCiAgKSkpCgpwbG90My5tYWxlLm1ldGEuQ1ZSLnBlcmMuYWxsIDwtIHBsb3QzLm1hbGUubWV0YS5DVlIucGVyYy5hbGwgJT4lIG11dGF0ZShHcm91cGluZ1Rlcm0gPSAiQWxsIikKCnBsb3QzLm1hbGUubWV0YS5WUi5wZXJjLmFsbCA8LSBtZXRhY29tYm9fbWFsZS5wbG90My5WUi5wZXJjLmFsbCAlPiUKICBtdXRhdGUobW9kZWxfbG5WUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuVlIsIHNlaSA9ICgueCRsblZSX3VwcGVyIC0gLngkbG5WUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCnBsb3QzLm1hbGUubWV0YS5WUi5wZXJjLmFsbCA8LSBwbG90My5tYWxlLm1ldGEuVlIucGVyYy5hbGwgJT4lIG11dGF0ZShHcm91cGluZ1Rlcm0gPSAiQWxsIikKCnBsb3QzLm1hbGUubWV0YS5SUi5wZXJjLmFsbCA8LSBtZXRhY29tYm9fbWFsZS5wbG90My5SUi5wZXJjLmFsbCAlPiUKICBtdXRhdGUobW9kZWxfbG5SUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuUlIsIHNlaSA9ICgueCRsblJSX3VwcGVyIC0gLngkbG5SUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCnBsb3QzLm1hbGUubWV0YS5SUi5wZXJjLmFsbCA8LSBwbG90My5tYWxlLm1ldGEuUlIucGVyYy5hbGwgJT4lIG11dGF0ZShHcm91cGluZ1Rlcm0gPSAiQWxsIikKCiMgQ29tYmluZSB3aXRoIHNlcGFyYXRlIGdyb3VwaW5nIHRlcm0gcmVzdWx0cwoKcGxvdDMubWFsZS5tZXRhLkNWUi5wZXJjIDwtIGJpbmRfcm93cyhwbG90My5tYWxlLm1ldGEuQ1ZSLnBlcmMsIHBsb3QzLm1hbGUubWV0YS5DVlIucGVyYy5hbGwpCnBsb3QzLm1hbGUubWV0YS5WUi5wZXJjIDwtIGJpbmRfcm93cyhwbG90My5tYWxlLm1ldGEuVlIucGVyYywgcGxvdDMubWFsZS5tZXRhLlZSLnBlcmMuYWxsKQpwbG90My5tYWxlLm1ldGEuUlIucGVyYyA8LSBiaW5kX3Jvd3MocGxvdDMubWFsZS5tZXRhLlJSLnBlcmMsIHBsb3QzLm1hbGUubWV0YS5SUi5wZXJjLmFsbCkKCgojICoqUmUtc3RydWN0dXJlIGRhdGEgZm9yIGVhY2ggZ3JvdXBpbmcgdGVybTsgZGVsZXRlIHVuLXVzZWQgdmFyaWFibGVzOiAiSGVhcmluZyBtaXNzaW5nIGZvciBhbGwgMyBwYXJhbWV0ZXJzIgoKcGxvdDMubWFsZS5tZXRhLkNWUi5wZXJjLmIgPC0gYXMuZGF0YS5mcmFtZShwbG90My5tYWxlLm1ldGEuQ1ZSLnBlcmMgJT4lIGdyb3VwX2J5KEdyb3VwaW5nVGVybSkgJT4lCiAgbXV0YXRlKAogICAgbG5DVlIgPSBtYXBfZGJsKG1vZGVsX2xuQ1ZSLCBwbHVjaygyKSksIGxuQ1ZSX2xvd2VyID0gbWFwX2RibChtb2RlbF9sbkNWUiwgcGx1Y2soNikpLAogICAgbG5DVlJfdXBwZXIgPSBtYXBfZGJsKG1vZGVsX2xuQ1ZSLCBwbHVjayg3KSksIGxuQ1ZSX3NlID0gbWFwX2RibChtb2RlbF9sbkNWUiwgcGx1Y2soMykpCiAgKSlbLCBjKDEsIDQ6NyldCmFkZC5yb3cuaGVhcmluZyA8LSBhcy5kYXRhLmZyYW1lKHQoYygiSGVhcmluZyIsIE5BLCBOQSwgTkEsIE5BKSkpICU+JSBzZXROYW1lcyhuYW1lcyhwbG90My5tYWxlLm1ldGEuQ1ZSLnBlcmMuYikpCnBsb3QzLm1hbGUubWV0YS5DVlIucGVyYy5iIDwtIHJiaW5kKHBsb3QzLm1hbGUubWV0YS5DVlIucGVyYy5iLCBhZGQucm93LmhlYXJpbmcpCnBsb3QzLm1hbGUubWV0YS5DVlIucGVyYy5iIDwtIHBsb3QzLm1hbGUubWV0YS5DVlIucGVyYy5iW29yZGVyKHBsb3QzLm1hbGUubWV0YS5DVlIucGVyYy5iJEdyb3VwaW5nVGVybSksIF0KCnBsb3QzLm1hbGUubWV0YS5WUi5wZXJjLmIgPC0gYXMuZGF0YS5mcmFtZShwbG90My5tYWxlLm1ldGEuVlIucGVyYyAlPiUgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBtdXRhdGUoCiAgICBsblZSID0gbWFwX2RibChtb2RlbF9sblZSLCBwbHVjaygyKSksIGxuVlJfbG93ZXIgPSBtYXBfZGJsKG1vZGVsX2xuVlIsIHBsdWNrKDYpKSwKICAgIGxuVlJfdXBwZXIgPSBtYXBfZGJsKG1vZGVsX2xuVlIsIHBsdWNrKDcpKSwgbG5WUl9zZSA9IG1hcF9kYmwobW9kZWxfbG5WUiwgcGx1Y2soMykpCiAgKSlbLCBjKDEsIDQ6NyldCmFkZC5yb3cuaGVhcmluZyA8LSBhcy5kYXRhLmZyYW1lKHQoYygiSGVhcmluZyIsIE5BLCBOQSwgTkEsIE5BKSkpICU+JSBzZXROYW1lcyhuYW1lcyhwbG90My5tYWxlLm1ldGEuVlIucGVyYy5iKSkKcGxvdDMubWFsZS5tZXRhLlZSLnBlcmMuYiA8LSByYmluZChwbG90My5tYWxlLm1ldGEuVlIucGVyYy5iLCBhZGQucm93LmhlYXJpbmcpCnBsb3QzLm1hbGUubWV0YS5WUi5wZXJjLmIgPC0gcGxvdDMubWFsZS5tZXRhLlZSLnBlcmMuYltvcmRlcihwbG90My5tYWxlLm1ldGEuVlIucGVyYy5iJEdyb3VwaW5nVGVybSksIF0KCnBsb3QzLm1hbGUubWV0YS5SUi5wZXJjLmIgPC0gYXMuZGF0YS5mcmFtZShwbG90My5tYWxlLm1ldGEuUlIucGVyYyAlPiUgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBtdXRhdGUoCiAgICBsblJSID0gbWFwX2RibChtb2RlbF9sblJSLCBwbHVjaygyKSksIGxuUlJfbG93ZXIgPSBtYXBfZGJsKG1vZGVsX2xuUlIsIHBsdWNrKDYpKSwKICAgIGxuUlJfdXBwZXIgPSBtYXBfZGJsKG1vZGVsX2xuUlIsIHBsdWNrKDcpKSwgbG5SUl9zZSA9IG1hcF9kYmwobW9kZWxfbG5SUiwgcGx1Y2soMykpCiAgKSlbLCBjKDEsIDQ6NyldCmFkZC5yb3cuaGVhcmluZyA8LSBhcy5kYXRhLmZyYW1lKHQoYygiSGVhcmluZyIsIE5BLCBOQSwgTkEsIE5BKSkpICU+JQogIHNldE5hbWVzKG5hbWVzKHBsb3QzLm1hbGUubWV0YS5SUi5wZXJjLmIpKQpwbG90My5tYWxlLm1ldGEuUlIucGVyYy5iIDwtIHJiaW5kKHBsb3QzLm1hbGUubWV0YS5SUi5wZXJjLmIsIGFkZC5yb3cuaGVhcmluZykKCmFkZC5yb3cuZXllIDwtIGFzLmRhdGEuZnJhbWUodChjKCJFeWUiLCBOQSwgTkEsIE5BLCBOQSkpKSAlPiUKICBzZXROYW1lcyhuYW1lcyhwbG90My5tYWxlLm1ldGEuUlIucGVyYy5iKSkKcGxvdDMubWFsZS5tZXRhLlJSLnBlcmMuYiA8LSByYmluZChwbG90My5tYWxlLm1ldGEuUlIucGVyYy5iLCBhZGQucm93LmV5ZSkKCnBsb3QzLm1hbGUubWV0YS5SUi5wZXJjLmIgPC0gcGxvdDMubWFsZS5tZXRhLlJSLnBlcmMuYltvcmRlcihwbG90My5tYWxlLm1ldGEuUlIucGVyYy5iJEdyb3VwaW5nVGVybSksIF0KCnBsb3QzLm1hbGUubWV0YS5DVlIuVnIucGVyYyA8LSBmdWxsX2pvaW4ocGxvdDMubWFsZS5tZXRhLkNWUi5wZXJjLmIsIHBsb3QzLm1hbGUubWV0YS5WUi5wZXJjLmIpCm92ZXJhbGwubWFsZS5wbG90My5wZXJjIDwtIGZ1bGxfam9pbihwbG90My5tYWxlLm1ldGEuQ1ZSLlZyLnBlcmMsIHBsb3QzLm1hbGUubWV0YS5SUi5wZXJjLmIpCgoKb3ZlcmFsbC5tYWxlLnBsb3QzLnBlcmMkR3JvdXBpbmdUZXJtIDwtIGZhY3RvcihvdmVyYWxsLm1hbGUucGxvdDMucGVyYyRHcm91cGluZ1Rlcm0sIGxldmVscyA9IGMoIkJlaGF2aW91ciIsICJNb3JwaG9sb2d5IiwgIk1ldGFib2xpc20iLCAiUGh5c2lvbG9neSIsICJJbW11bm9sb2d5IiwgIkhlbWF0b2xvZ3kiLCAiSGVhcnQiLCAiSGVhcmluZyIsICJFeWUiLCAiQWxsIikpCm92ZXJhbGwubWFsZS5wbG90My5wZXJjJEdyb3VwaW5nVGVybSA8LSBmYWN0b3Iob3ZlcmFsbC5tYWxlLnBsb3QzLnBlcmMkR3JvdXBpbmdUZXJtLCByZXYobGV2ZWxzKG92ZXJhbGwubWFsZS5wbG90My5wZXJjJEdyb3VwaW5nVGVybSkpKQpgYGAKClJlc3RydWN0dXJlIGRhdGEgZm9yIHBsb3R0aW5nIDogTWFsZSBiaWFzZWQsIDEwJSBkaWZmZXJlbmNlCgpgYGB7cn0Kb3ZlcmFsbDMucGVyYyA8LSBnYXRoZXIob3ZlcmFsbC5tYWxlLnBsb3QzLnBlcmMsIHBhcmFtZXRlciwgdmFsdWUsIGMobG5DVlIsIGxuVlIsIGxuUlIpLCBmYWN0b3Jfa2V5ID0gVFJVRSkgCgpsbkNWUi5jaSA8LSBvdmVyYWxsMy5wZXJjICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuQ1ZSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuQ1ZSX2xvd2VyLCBjaS5oaWdoID0gbG5DVlJfdXBwZXIpCmxuVlIuY2kgPC0gb3ZlcmFsbDMucGVyYyAgJT4lIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuVlIiKSAlPiUgbXV0YXRlKGNpLmxvdyA9IGxuVlJfbG93ZXIsIGNpLmhpZ2ggPSBsblZSX3VwcGVyKQpsblJSLmNpIDwtIG92ZXJhbGwzLnBlcmMgJT4lCiAgZmlsdGVyKHBhcmFtZXRlciA9PSAibG5SUiIpICU+JQogIG11dGF0ZShjaS5sb3cgPSBsblJSX2xvd2VyLCBjaS5oaWdoID0gbG5SUl91cHBlcikKCm92ZXJhbGw0Lm1hbGUucGVyYyA8LSBiaW5kX3Jvd3MobG5DVlIuY2ksbG5WUi5jaSwgbG5SUi5jaSkgJT4lIHNlbGVjdChHcm91cGluZ1Rlcm0sIHBhcmFtZXRlciwgdmFsdWUsIGNpLmxvdywgY2kuaGlnaCkgCgpvdmVyYWxsNC5tYWxlLnBlcmMkbGFiZWwgPC0gIlNleCBkaWZmZXJlbmNlIGluIG0vZiByYXRpb3MgPiAxMCUiCgpvdmVyYWxsNC5tYWxlLnBlcmMkdmFsdWUgPC0gYXMubnVtZXJpYyhvdmVyYWxsNC5tYWxlLnBlcmMkdmFsdWUpCm92ZXJhbGw0Lm1hbGUucGVyYyRjaS5sb3cgPC0gYXMubnVtZXJpYyhvdmVyYWxsNC5tYWxlLnBlcmMkY2kubG93KQpvdmVyYWxsNC5tYWxlLnBlcmMkY2kuaGlnaCA8LSBhcy5udW1lcmljKG92ZXJhbGw0Lm1hbGUucGVyYyRjaS5oaWdoKQpgYGAKClBsb3QgRmlnIFMyIGFsbCA+MTAlIGRpZmZlcmVuY2UgKG1hbGUgYmlhcykKCmBgYHtyfQoKTWV0YW1ldGFfRmlnM19tYWxlLnBlcmMgPC0gb3ZlcmFsbDQubWFsZS5wZXJjICU+JSAjIGZpbHRlciguLCBHcm91cGluZ1Rlcm0gIT0gIkhlYXJpbmciKSAlPiUKICBnZ3Bsb3QoYWVzKHkgPSBHcm91cGluZ1Rlcm0sIHggPSB2YWx1ZSkpICsKICBnZW9tX2Vycm9yYmFyaChhZXMoCiAgICB4bWluID0gY2kubG93LAogICAgeG1heCA9IGNpLmhpZ2gKICApLAogIGhlaWdodCA9IDAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRQogICkgKwogIGdlb21fcG9pbnQoYWVzKAogICAgc2hhcGUgPSBwYXJhbWV0ZXIsCiAgICBmaWxsID0gcGFyYW1ldGVyCiAgKSwKICBjb2xvciA9ICJtZWRpdW1hcXVhbWFyaW5lIiwgc2l6ZSA9IDIuMiwKICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgc2NhbGVfeF9jb250aW51b3VzKAogICAgbGltaXRzID0gYygtMC4yLCAwLjYyKSwKICAgIGJyZWFrcyA9IGMoMCwgMC4zKSwKICAgIG5hbWUgPSAiRWZmZWN0IHNpemUiCiAgKSArCiAgZ2VvbV92bGluZSgKICAgIHhpbnRlcmNlcHQgPSAwLAogICAgY29sb3IgPSAiYmxhY2siLAogICAgbGluZXR5cGUgPSAiZGFzaGVkIgogICkgKwogIGZhY2V0X2dyaWQoCiAgICBjb2xzID0gdmFycyhwYXJhbWV0ZXIpLCByb3dzID0gdmFycyhsYWJlbCksCiAgICBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMjMpLAogICAgc2NhbGVzID0gImZyZWUiLAogICAgc3BhY2UgPSAiZnJlZSIKICApICsKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgc2l6ZSA9IDEwLCBtYXJnaW4gPSBtYXJnaW4odCA9IDE1LCByID0gMTUsIGIgPSAxNSwgbCA9IDE1KSksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5VTEwsIGxpbmV0eXBlID0gImJsYW5rIiwgZmlsbCA9ICJncmF5OTAiKSwKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDAuNSwgImxpbmVzIiksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG91ciA9ICJncmF5OTUiKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG9yID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTQpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpCiAgKQoKIyBNZXRhbWV0YV9GaWczX21hbGUucGVyYyAoRmlndXJlIFMyIHJpZ2h0IHBhbmVsKQpgYGAKCiMjIyMgRmVtYWxlIEZpZyBTMiA+MTAlCgpgYGB7cn0KCm1ldGEucGxvdDMucGVyYyA8LSBtZXRhY29tYm8gJT4lCiAgbXV0YXRlKAogICAgcGVyY0NWUiA9IGlmZWxzZShsbkNWUiA8IGxvZyg5IC8gMTApLCAxLCAwKSwKICAgIHBlcmNWUiA9IGlmZWxzZShsblZSIDwgbG9nKDkgLyAxMCksIDEsIDApLAogICAgcGVyY1JSID0gaWZlbHNlKGxuUlIgPCBsb2coOSAvIDEwKSwgMSwgMCkKICApCgojIFNpZ25pZmljYW50IHN1YnNldCBmb3IgbG5DVlIKbWV0YWNvbWJvX3Bsb3QzLkNWUi5wZXJjIDwtIG1ldGEucGxvdDMucGVyYyAlPiUKICBmaWx0ZXIocGVyY0NWUiA9PSAxKSAlPiUKICBncm91cF9ieShHcm91cGluZ1Rlcm0pICU+JQogIG5lc3QoKQoKbWV0YWNvbWJvX3Bsb3QzLkNWUi5wZXJjLmFsbCA8LSBtZXRhLnBsb3QzLnBlcmMgJT4lCiAgZmlsdGVyKHBlcmNDVlIgPT0gMSkgJT4lCiAgbmVzdCgpCgojIFNpZ25pZmljYW50IHN1YnNldCBmb3IgbG5WUgptZXRhY29tYm9fcGxvdDMuVlIucGVyYyA8LSBtZXRhLnBsb3QzLnBlcmMgJT4lCiAgZmlsdGVyKHBlcmNWUiA9PSAxKSAlPiUKICBncm91cF9ieShHcm91cGluZ1Rlcm0pICU+JQogIG5lc3QoKQoKbWV0YWNvbWJvX3Bsb3QzLlZSLnBlcmMuYWxsIDwtIG1ldGEucGxvdDMucGVyYyAlPiUKICBmaWx0ZXIocGVyY1ZSID09IDEpICU+JQogIG5lc3QoKQoKIyBTaWduaWZpY2FudCBzdWJzZXQgZm9yIGxuUlIKbWV0YWNvbWJvX3Bsb3QzLlJSLnBlcmMgPC0gbWV0YS5wbG90My5wZXJjICU+JQogIGZpbHRlcihwZXJjUlIgPT0gMSkgJT4lCiAgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBuZXN0KCkKCm1ldGFjb21ib19wbG90My5SUi5wZXJjLmFsbCA8LSBtZXRhLnBsb3QzLnBlcmMgJT4lCiAgZmlsdGVyKHBlcmNSUiA9PSAxKSAlPiUKICBuZXN0KCkKCgojICoqRmluYWwgZml4ZWQgZWZmZWN0cyBtZXRhLWFuYWx5c2VzIHdpdGhpbiBncm91cGluZyB0ZXJtcywgd2l0aCBTRSBvZiB0aGUgZXN0aW1hdGUKCnBsb3QzLm1ldGEuQ1ZSLnBlcmMgPC0gbWV0YWNvbWJvX3Bsb3QzLkNWUi5wZXJjICU+JQogIG11dGF0ZShtb2RlbF9sbkNWUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuQ1ZSLCBzZWkgPSAoLngkbG5DVlJfdXBwZXIgLSAueCRsbkNWUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCnBsb3QzLm1ldGEuVlIucGVyYyA8LSBtZXRhY29tYm9fcGxvdDMuVlIucGVyYyAlPiUKICBtdXRhdGUobW9kZWxfbG5WUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuVlIsIHNlaSA9ICgueCRsblZSX3VwcGVyIC0gLngkbG5WUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCnBsb3QzLm1ldGEuUlIucGVyYyA8LSBtZXRhY29tYm9fcGxvdDMuUlIucGVyYyAlPiUKICBtdXRhdGUobW9kZWxfbG5SUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuUlIsIHNlaSA9ICgueCRsblJSX3VwcGVyIC0gLngkbG5SUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCiMgQWNyb3NzIGFsbCBncm91cGluZyB0ZXJtcyAjCgpwbG90My5tZXRhLkNWUi5wZXJjLmFsbCA8LSBtZXRhY29tYm9fcGxvdDMuQ1ZSLnBlcmMuYWxsICU+JQogIG11dGF0ZShtb2RlbF9sbkNWUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuQ1ZSLCBzZWkgPSAoLngkbG5DVlJfdXBwZXIgLSAueCRsbkNWUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCnBsb3QzLm1ldGEuQ1ZSLnBlcmMuYWxsIDwtIHBsb3QzLm1ldGEuQ1ZSLnBlcmMuYWxsICU+JSBtdXRhdGUoR3JvdXBpbmdUZXJtID0gIkFsbCIpCgpwbG90My5tZXRhLlZSLnBlcmMuYWxsIDwtIG1ldGFjb21ib19wbG90My5WUi5wZXJjLmFsbCAlPiUKICBtdXRhdGUobW9kZWxfbG5WUiA9IG1hcChkYXRhLCB+IG1ldGFmb3I6OnJtYS51bmkoCiAgICB5aSA9IC54JGxuVlIsIHNlaSA9ICgueCRsblZSX3VwcGVyIC0gLngkbG5WUl9sb3dlcikgLyAoMiAqIDEuOTYpLAogICAgY29udHJvbCA9IGxpc3Qob3B0aW1pemVyID0gIm9wdGltIiwgb3B0bWV0aG9kID0gIk5lbGRlci1NZWFkIiwgbWF4aXQgPSAxMDAwKSwgdmVyYm9zZSA9IEYKICApKSkKCnBsb3QzLm1ldGEuVlIucGVyYy5hbGwgPC0gcGxvdDMubWV0YS5WUi5wZXJjLmFsbCAlPiUgbXV0YXRlKEdyb3VwaW5nVGVybSA9ICJBbGwiKQoKcGxvdDMubWV0YS5SUi5wZXJjLmFsbCA8LSBtZXRhY29tYm9fcGxvdDMuUlIucGVyYy5hbGwgJT4lCiAgbXV0YXRlKG1vZGVsX2xuUlIgPSBtYXAoZGF0YSwgfiBtZXRhZm9yOjpybWEudW5pKAogICAgeWkgPSAueCRsblJSLCBzZWkgPSAoLngkbG5SUl91cHBlciAtIC54JGxuUlJfbG93ZXIpIC8gKDIgKiAxLjk2KSwKICAgIGNvbnRyb2wgPSBsaXN0KG9wdGltaXplciA9ICJvcHRpbSIsIG9wdG1ldGhvZCA9ICJOZWxkZXItTWVhZCIsIG1heGl0ID0gMTAwMCksIHZlcmJvc2UgPSBGCiAgKSkpCgpwbG90My5tZXRhLlJSLnBlcmMuYWxsIDwtIHBsb3QzLm1ldGEuUlIucGVyYy5hbGwgJT4lIG11dGF0ZShHcm91cGluZ1Rlcm0gPSAiQWxsIikKCiMgQ29tYmluZSB3aXRoIHNlcGFyYXRlIGdyb3VwaW5nIHRlcm0gcmVzdWx0cwoKcGxvdDMubWV0YS5DVlIucGVyYyA8LSBiaW5kX3Jvd3MocGxvdDMubWV0YS5DVlIucGVyYywgcGxvdDMubWV0YS5DVlIucGVyYy5hbGwpCnBsb3QzLm1ldGEuVlIucGVyYyA8LSBiaW5kX3Jvd3MocGxvdDMubWV0YS5WUi5wZXJjLCBwbG90My5tZXRhLlZSLnBlcmMuYWxsKQpwbG90My5tZXRhLlJSLnBlcmMgPC0gYmluZF9yb3dzKHBsb3QzLm1ldGEuUlIucGVyYywgcGxvdDMubWV0YS5SUi5wZXJjLmFsbCkKCgojICoqUmUtc3RydWN0dXJlIGRhdGEgZm9yIGVhY2ggZ3JvdXBpbmcgdGVybTsgZGVsZXRlIHVuLXVzZWQgdmFyaWFibGVzOiAiSGVhcmluZyBtaXNzaW5nIGZvciBhbGwgMyBwYXJhbWV0ZXJzIgoKcGxvdDMubWV0YS5DVlIucGVyYy5iIDwtIGFzLmRhdGEuZnJhbWUocGxvdDMubWV0YS5DVlIucGVyYyAlPiUgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBtdXRhdGUoCiAgICBsbkNWUiA9IG1hcF9kYmwobW9kZWxfbG5DVlIsIHBsdWNrKDIpKSwgbG5DVlJfbG93ZXIgPSBtYXBfZGJsKG1vZGVsX2xuQ1ZSLCBwbHVjayg2KSksCiAgICBsbkNWUl91cHBlciA9IG1hcF9kYmwobW9kZWxfbG5DVlIsIHBsdWNrKDcpKSwgbG5DVlJfc2UgPSBtYXBfZGJsKG1vZGVsX2xuQ1ZSLCBwbHVjaygzKSkKICApKVssIGMoMSwgNDo3KV0KYWRkLnJvdy5oZWFyaW5nIDwtIGFzLmRhdGEuZnJhbWUodChjKCJIZWFyaW5nIiwgTkEsIE5BLCBOQSwgTkEpKSkgJT4lIHNldE5hbWVzKG5hbWVzKHBsb3QzLm1ldGEuQ1ZSLnBlcmMuYikpCnBsb3QzLm1ldGEuQ1ZSLnBlcmMuYiA8LSByYmluZChwbG90My5tZXRhLkNWUi5wZXJjLmIsIGFkZC5yb3cuaGVhcmluZykKcGxvdDMubWV0YS5DVlIucGVyYy5iIDwtIHBsb3QzLm1ldGEuQ1ZSLnBlcmMuYltvcmRlcihwbG90My5tZXRhLkNWUi5wZXJjLmIkR3JvdXBpbmdUZXJtKSwgXQoKcGxvdDMubWV0YS5WUi5wZXJjLmIgPC0gYXMuZGF0YS5mcmFtZShwbG90My5tZXRhLlZSLnBlcmMgJT4lIGdyb3VwX2J5KEdyb3VwaW5nVGVybSkgJT4lCiAgbXV0YXRlKAogICAgbG5WUiA9IG1hcF9kYmwobW9kZWxfbG5WUiwgcGx1Y2soMikpLCBsblZSX2xvd2VyID0gbWFwX2RibChtb2RlbF9sblZSLCBwbHVjayg2KSksCiAgICBsblZSX3VwcGVyID0gbWFwX2RibChtb2RlbF9sblZSLCBwbHVjayg3KSksIGxuVlJfc2UgPSBtYXBfZGJsKG1vZGVsX2xuVlIsIHBsdWNrKDMpKQogICkpWywgYygxLCA0OjcpXQphZGQucm93LmhlYXJpbmcgPC0gYXMuZGF0YS5mcmFtZSh0KGMoIkhlYXJpbmciLCBOQSwgTkEsIE5BLCBOQSkpKSAlPiUgc2V0TmFtZXMobmFtZXMocGxvdDMubWV0YS5WUi5wZXJjLmIpKQpwbG90My5tZXRhLlZSLnBlcmMuYiA8LSByYmluZChwbG90My5tZXRhLlZSLnBlcmMuYiwgYWRkLnJvdy5oZWFyaW5nKQpwbG90My5tZXRhLlZSLnBlcmMuYiA8LSBwbG90My5tZXRhLlZSLnBlcmMuYltvcmRlcihwbG90My5tZXRhLlZSLnBlcmMuYiRHcm91cGluZ1Rlcm0pLCBdCgpwbG90My5tZXRhLlJSLnBlcmMuYiA8LSBhcy5kYXRhLmZyYW1lKHBsb3QzLm1ldGEuUlIucGVyYyAlPiUgZ3JvdXBfYnkoR3JvdXBpbmdUZXJtKSAlPiUKICBtdXRhdGUoCiAgICBsblJSID0gbWFwX2RibChtb2RlbF9sblJSLCBwbHVjaygyKSksIGxuUlJfbG93ZXIgPSBtYXBfZGJsKG1vZGVsX2xuUlIsIHBsdWNrKDYpKSwKICAgIGxuUlJfdXBwZXIgPSBtYXBfZGJsKG1vZGVsX2xuUlIsIHBsdWNrKDcpKSwgbG5SUl9zZSA9IG1hcF9kYmwobW9kZWxfbG5SUiwgcGx1Y2soMykpCiAgKSlbLCBjKDEsIDQ6NyldCmFkZC5yb3cuaGVhcmluZyA8LSBhcy5kYXRhLmZyYW1lKHQoYygiSGVhcmluZyIsIE5BLCBOQSwgTkEsIE5BKSkpICU+JSBzZXROYW1lcyhuYW1lcyhwbG90My5tZXRhLlJSLnBlcmMuYikpCnBsb3QzLm1ldGEuUlIucGVyYy5iIDwtIHJiaW5kKHBsb3QzLm1ldGEuUlIucGVyYy5iLCBhZGQucm93LmhlYXJpbmcpCmFkZC5yb3cuaGVtYXRvbG9neSA8LSBhcy5kYXRhLmZyYW1lKHQoYygiSGVtYXRvbG9neSIsIE5BLCBOQSwgTkEsIE5BKSkpICU+JQogIHNldE5hbWVzKG5hbWVzKHBsb3QzLm1ldGEuUlIucGVyYy5iKSkKcGxvdDMubWV0YS5SUi5wZXJjLmIgPC0gcmJpbmQocGxvdDMubWV0YS5SUi5wZXJjLmIsIGFkZC5yb3cuaGVtYXRvbG9neSkKCgpwbG90My5tZXRhLlJSLnBlcmMuYiA8LSBwbG90My5tZXRhLlJSLnBlcmMuYltvcmRlcihwbG90My5tZXRhLlJSLnBlcmMuYiRHcm91cGluZ1Rlcm0pLCBdCgpwbG90My5tZXRhLkNWUi5wZXJjLmMgPC0gZnVsbF9qb2luKHBsb3QzLm1ldGEuQ1ZSLnBlcmMuYiwgcGxvdDMubWV0YS5WUi5wZXJjLmIpCm92ZXJhbGwucGxvdDMucGVyYyA8LSBmdWxsX2pvaW4ocGxvdDMubWV0YS5DVlIucGVyYy5jLCBwbG90My5tZXRhLlJSLnBlcmMuYikKCgpvdmVyYWxsLnBsb3QzLnBlcmMkR3JvdXBpbmdUZXJtIDwtIGZhY3RvcihvdmVyYWxsLnBsb3QzLnBlcmMkR3JvdXBpbmdUZXJtLCBsZXZlbHMgPSBjKCJCZWhhdmlvdXIiLCAiTW9ycGhvbG9neSIsICJNZXRhYm9saXNtIiwgIlBoeXNpb2xvZ3kiLCAiSW1tdW5vbG9neSIsICJIZW1hdG9sb2d5IiwgIkhlYXJ0IiwgIkhlYXJpbmciLCAiRXllIiwgIkFsbCIpKQpvdmVyYWxsLnBsb3QzLnBlcmMkR3JvdXBpbmdUZXJtIDwtIGZhY3RvcihvdmVyYWxsLnBsb3QzLnBlcmMkR3JvdXBpbmdUZXJtLCByZXYobGV2ZWxzKG92ZXJhbGwucGxvdDMucGVyYyRHcm91cGluZ1Rlcm0pKSkKYGBgCgpSZXN0cnVjdHVyZSBkYXRhIGZvciBwbG90dGluZwpGZW1hbGUgYmlhcywgMTAgcGVyY2VudCBkaWZmZXJlbmNlCgpgYGB7cn0Kb3ZlcmFsbDMucGVyYyA8LSBnYXRoZXIob3ZlcmFsbC5wbG90My5wZXJjLCBwYXJhbWV0ZXIsIHZhbHVlLCBjKGxuQ1ZSLCBsblZSLCBsblJSKSwgZmFjdG9yX2tleSA9IFRSVUUpIAoKbG5DVlIuY2kgPC0gb3ZlcmFsbDMucGVyYyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJsbkNWUiIpICU+JQogIG11dGF0ZShjaS5sb3cgPSBsbkNWUl9sb3dlciwgY2kuaGlnaCA9IGxuQ1ZSX3VwcGVyKQpsblZSLmNpIDwtIG92ZXJhbGwzLnBlcmMgICU+JSBmaWx0ZXIocGFyYW1ldGVyID09ICJsblZSIikgJT4lIG11dGF0ZShjaS5sb3cgPSBsblZSX2xvd2VyLCBjaS5oaWdoID0gbG5WUl91cHBlcikKbG5SUi5jaSA8LSBvdmVyYWxsMy5wZXJjICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuUlIiKSAlPiUKICBtdXRhdGUoY2kubG93ID0gbG5SUl9sb3dlciwgY2kuaGlnaCA9IGxuUlJfdXBwZXIpCgpvdmVyYWxsNC5wZXJjIDwtIGJpbmRfcm93cyhsbkNWUi5jaSwgbG5WUi5jaSwgbG5SUi5jaSkgJT4lIHNlbGVjdChHcm91cGluZ1Rlcm0sIHBhcmFtZXRlciwgdmFsdWUsIGNpLmxvdywgY2kuaGlnaCkKCm92ZXJhbGw0LnBlcmMkbGFiZWwgPC0gIlNleCBkaWZmZXJlbmNlIGluIG0vZiByYXRpb3MgPiAxMCUiCgpvdmVyYWxsNC5wZXJjJHZhbHVlIDwtIGFzLm51bWVyaWMob3ZlcmFsbDQucGVyYyR2YWx1ZSkKb3ZlcmFsbDQucGVyYyRjaS5sb3cgPC0gYXMubnVtZXJpYyhvdmVyYWxsNC5wZXJjJGNpLmxvdykKb3ZlcmFsbDQucGVyYyRjaS5oaWdoIDwtIGFzLm51bWVyaWMob3ZlcmFsbDQucGVyYyRjaS5oaWdoKQpgYGAKClBsb3QgRmlnUzIgYWxsID4xMCUgZGlmZmVyZW5jZSAoZmVtYWxlKQoKYGBge3J9Ck1ldGFtZXRhX0ZpZzNfZmVtYWxlLnBlcmMgPC0gb3ZlcmFsbDQucGVyYyAlPiUKICBnZ3Bsb3QoYWVzKHkgPSBHcm91cGluZ1Rlcm0sIHggPSB2YWx1ZSkpICsKICBnZW9tX2Vycm9yYmFyaChhZXMoCiAgICB4bWluID0gY2kubG93LAogICAgeG1heCA9IGNpLmhpZ2gKICApLAogIGhlaWdodCA9IDAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRQogICkgKwogIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gcGFyYW1ldGVyKSwKICAgIGZpbGwgPSAic2FsbW9uMSIsIGNvbG9yID0gInNhbG1vbjEiLCBzaXplID0gMi4yLAogICAgc2hvdy5sZWdlbmQgPSBGQUxTRQogICkgKwoKICAjIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPQoKICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICBsaW1pdHMgPSBjKC0wLjUzLCAwLjIpLAogICAgYnJlYWtzID0gYygtMC4zLCAwKSwKICAgIG5hbWUgPSAiRWZmZWN0IHNpemUiCiAgKSArCiAgZ2VvbV92bGluZSgKICAgIHhpbnRlcmNlcHQgPSAwLAogICAgY29sb3IgPSAiYmxhY2siLAogICAgbGluZXR5cGUgPSAiZGFzaGVkIgogICkgKwogIGZhY2V0X2dyaWQoCiAgICBjb2xzID0gdmFycyhwYXJhbWV0ZXIpLCAjIHJvd3MgPSB2YXJzKGxhYmVsKSwKICAgICMgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDIzKSwKICAgIHNjYWxlcyA9ICJmcmVlIiwKICAgIHNwYWNlID0gImZyZWUiCiAgKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoCiAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNzAsIHNpemUgPSAxMCwgbWFyZ2luID0gbWFyZ2luKHQgPSAxNSwgciA9IDE1LCBiID0gMTUsIGwgPSAxNSkpLAogICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSBOVUxMLCBsaW5ldHlwZSA9ICJibGFuayIsIGZpbGwgPSAiZ3JheTkwIiksCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgwLjUsICJsaW5lcyIpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKCksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAic29saWQiLCBjb2xvdXIgPSAiZ3JheTk1IiksCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAic29saWQiLCBjb2xvciA9ICJncmF5OTUiKSwKICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE0KSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKQogICkKCiMgTWV0YW1ldGFfRmlnM19mZW1hbGUucGVyYyAoRmlndXJlIDVEIGxlZnQgcGFuZWwpCmBgYAoKIyMjIyBQbG90IEZpZyBTMjogICBwbG90cyBjb21iaW5lZApgYGB7cn0KbGlicmFyeShnZ3B1YnIpCkZpZ1MyYiA8LSBnZ2FycmFuZ2UoTWV0YW1ldGFfRmlnM19mZW1hbGUuc2lnLCBNZXRhbWV0YV9GaWczX21hbGUuc2lnLAogIG5jb2wgPSAyLCBucm93ID0gMSwgd2lkdGhzID0gYygxLCAxLjIwKSwgaGVpZ2h0cyA9IGMoMSwgMSkKKQoKRmlnUzJkIDwtIGdnYXJyYW5nZShNZXRhbWV0YV9GaWczX2ZlbWFsZS5wZXJjLCBNZXRhbWV0YV9GaWczX21hbGUucGVyYywKICBuY29sID0gMiwgbnJvdyA9IDEsIHdpZHRocyA9IGMoMSwgMS4yMCksIGhlaWdodHMgPSBjKDEsIDEpCikKCiMgZW5kIGNvbWJpbmF0aW9uIEZpZ3VyZSA1CkZpZ1MyIDwtIGdnYXJyYW5nZShtYWxlYmlhc19GaWdTMl9zaWd0cmFpdHMsIG1hbGViaWFzX0ZpZzJfb3ZlcjEwLCBGaWdTMmIsIEZpZ1MyZCwgbmNvbCA9IDEsIG5yb3cgPSA0LCBoZWlnaHRzID0gYygyLjMsIDIsIDIuMSwgMiksIGxhYmVscyA9IGMoIkEiLCAiICIsICJCIiwgIiAiKSkKRmlnUzIKYGBgCgojIyBOT1QgU1VSRSBXSEFUIFRISVMgQkVMT1cgSVM/PwoKIyMgRmlndXJlIFMyOiBzZXgtYmlhcywgaW5jbHVkaW5nIFZSCgpQcmVwYXJlIGRhdGEgZm9yIHRyYWl0cyB3aXRoIGVmZmVjdCBzaXplIHJhdGlvcyA+IDEwJSBsYXJnZXIgaW4gbWFsZXMKCmBgYHtyfQptZXRhLnBsb3RTMi5vdmVyMTAgPC0gbWV0YV9jbGVhbiAlPiUKICBzZWxlY3QobG5DVlIsIGxuVlIsIGxuUlIsIEdyb3VwaW5nVGVybSkgJT4lCiAgYXJyYW5nZShHcm91cGluZ1Rlcm0pCgptZXRhLnBsb3RTMi5vdmVyMTAuYiA8LSBnYXRoZXIobWV0YS5wbG90UzIub3ZlcjEwLCB0cmFpdCwgdmFsdWUsIGMobG5DVlIsIGxuVlIsIGxuUlIpKQoKbWV0YS5wbG90UzIub3ZlcjEwLmIkdHJhaXQgPC0gZmFjdG9yKG1ldGEucGxvdFMyLm92ZXIxMC5iJHRyYWl0LCBsZXZlbHMgPSBjKCJsbkNWUiIsICJsblZSIiwgImxuUlIiKSkKCm1ldGEucGxvdFMyLm92ZXIxMC5jIDwtIG1ldGEucGxvdFMyLm92ZXIxMC5iICU+JQogIGdyb3VwX2J5X2F0KHZhcnModHJhaXQsIEdyb3VwaW5nVGVybSkpICU+JQogIHN1bW1hcmlzZSgKICAgIG1hbGViaWFzID0gc3VtKHZhbHVlID4gbG9nKDExIC8gMTApKSwgZmVtYWxlYmlhcyA9IHN1bSh2YWx1ZSA8IGxvZyg5IC8gMTApKSwgdG90YWwgPSBtYWxlYmlhcyArIGZlbWFsZWJpYXMsCiAgICBtYWxlcGVyY2VudCA9IG1hbGViaWFzICogMTAwIC8gdG90YWwsIGZlbWFsZXBlcmNlbnQgPSBmZW1hbGViaWFzICogMTAwIC8gdG90YWwKICApCgptZXRhLnBsb3RTMi5vdmVyMTAuYyRsYWJlbCA8LSAiU2V4IGRpZmZlcmVuY2UgaW4gbS9mIHJhdGlvcyA+IDEwJSIKCiMgcmVzdHJ1Y3R1cmUgdG8gY3JlYXRlIHN0YWNrZWQgYmFyIHBsb3RzCgptZXRhLnBsb3RTMi5vdmVyMTAuYyA8LSBhcy5kYXRhLmZyYW1lKG1ldGEucGxvdFMyLm92ZXIxMC5jKQptZXRhLnBsb3RTMi5vdmVyMTAuZCA8LSBnYXRoZXIobWV0YS5wbG90UzIub3ZlcjEwLmMsIGtleSA9IHNleCwgdmFsdWUgPSBwZXJjZW50LCBtYWxlcGVyY2VudDpmZW1hbGVwZXJjZW50LCBmYWN0b3Jfa2V5ID0gVFJVRSkKCiMgY3JlYXRlIG5ldyBzYW1wbGUgc2l6ZSB2YXJpYWJsZQoKbWV0YS5wbG90UzIub3ZlcjEwLmQkc2FtcGxlc2l6ZSA8LSB3aXRoKG1ldGEucGxvdFMyLm92ZXIxMC5kLCBpZmVsc2Uoc2V4ID09ICJtYWxlcGVyY2VudCIsIG1hbGViaWFzLCBmZW1hbGViaWFzKSkKCiMgKlBsb3QgRmlnUzIgU2V4IGRpZmZlcmVuY2UgaW4gbS9mIHJhdGlvID4gMTAlCm1hbGViaWFzX0ZpZ1MyX292ZXIxMCA8LQogIGdncGxvdChtZXRhLnBsb3RTMi5vdmVyMTAuZCkgKwogIGFlcyh4ID0gR3JvdXBpbmdUZXJtLCB5ID0gcGVyY2VudCwgZmlsbCA9IHNleCkgKwogIGdlb21fY29sKCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDUwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5NDAiKSArCiAgZ2VvbV90ZXh0KAogICAgZGF0YSA9IHN1YnNldChtZXRhLnBsb3QyLm92ZXIxMC5kLCBzYW1wbGVzaXplICE9IDApLCBhZXMobGFiZWwgPSBzYW1wbGVzaXplKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSwKICAgIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDMuNQogICkgKwogIGZhY2V0X2dyaWQoCiAgICBjb2xzID0gdmFycyh0cmFpdCksIHJvd3MgPSB2YXJzKGxhYmVsKSwgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDE4KSwKICAgIHNjYWxlcyA9ICJmcmVlIiwgc3BhY2UgPSAiZnJlZSIKICApICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTgpICsKICB0aGVtZSgKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgc2l6ZSA9IDEwLCBtYXJnaW4gPSBtYXJnaW4odCA9IDE1LCByID0gMTUsIGIgPSAxNSwgbCA9IDE1KSksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5VTEwsIGxpbmV0eXBlID0gImJsYW5rIiwgZmlsbCA9ICJncmF5OTAiKSwKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDAuNSwgImxpbmVzIiksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG91ciA9ICJncmF5OTUiKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG9yID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpCiAgKSArCiAgY29vcmRfZmxpcCgpCgojIG1hbGViaWFzX0ZpZ1MyX292ZXIxMCAgIyhQYW5lbCBCIGluIEZpZyBTMiBpbiBtcykKYGBgCgoKCiNNZXRhbWV0YV9GaWdTMl9tYWxlLnNpZyAoRmlndXJlIDVCIHJpZ2h0IHBhbmVsKQoKUmVzdHJ1Y3R1cmUgTUFMRSBkYXRhIGZvciBwbG90dGluZyAKCmBgYHtyfQpvdmVyYWxsMy5tYWxlLnNpZ1MgPC0gZ2F0aGVyKG92ZXJhbGwubWFsZS5wbG90MywgcGFyYW1ldGVyLCB2YWx1ZSwgYyhsbkNWUiwgbG5WUiwgbG5SUiksIGZhY3Rvcl9rZXkgPSBUUlVFKQoKCmxuQ1ZSLmNpIDwtIG92ZXJhbGwzLm1hbGUuc2lnUyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJsbkNWUiIpICU+JQogIG11dGF0ZShjaS5sb3cgPSBsbkNWUl9sb3dlciwgY2kuaGlnaCA9IGxuQ1ZSX3VwcGVyKQpsblZSLmNpIDwtIG92ZXJhbGwzLm1hbGUuc2lnUyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJsblZSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuVlJfbG93ZXIsIGNpLmhpZ2ggPSBsblZSX3VwcGVyKQpsblJSLmNpIDwtIG92ZXJhbGwzLm1hbGUuc2lnUyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJsblJSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuUlJfbG93ZXIsIGNpLmhpZ2ggPSBsblJSX3VwcGVyKQoKb3ZlcmFsbDQubWFsZS5zaWdTIDwtIGJpbmRfcm93cyhsbkNWUi5jaSwgbG5WUi5jaSwgbG5SUi5jaSkgJT4lIHNlbGVjdChHcm91cGluZ1Rlcm0sIHBhcmFtZXRlciwgdmFsdWUsIGNpLmxvdywgY2kuaGlnaCkKCm92ZXJhbGw0Lm1hbGUuc2lnUyRsYWJlbCA8LSAiQ0kgbm90IG92ZXJsYXBwaW5nIHplcm8iCmBgYAoKUGxvdCBGaWdTMiBhbGwgc2lnbmlmaWNhbnQgcmVzdWx0cyAoQ0kgbm90IG92ZXJsYXBwaW5nIHplcm8sIG1hbGUgKQoKYGBge3J9Ck1ldGFtZXRhX0ZpZ1MyX21hbGUuc2lnIDwtIG92ZXJhbGw0Lm1hbGUuc2lnUyAlPiUKICBnZ3Bsb3QoYWVzKHkgPSBHcm91cGluZ1Rlcm0sIHggPSB2YWx1ZSkpICsKICBnZW9tX2Vycm9yYmFyaChhZXMoCiAgICB4bWluID0gY2kubG93LAogICAgeG1heCA9IGNpLmhpZ2gKICApLAogIGhlaWdodCA9IDAuMSwgc2hvdy5sZWdlbmQgPSBGQUxTRQogICkgKwogIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gcGFyYW1ldGVyKSwKICAgIGZpbGwgPSAibWVkaXVtYXF1YW1hcmluZSIsIGNvbG9yID0gIm1lZGl1bWFxdWFtYXJpbmUiLCBzaXplID0gMi4yLAogICAgc2hvdy5sZWdlbmQgPSBGQUxTRQogICkgKwogIHNjYWxlX3hfY29udGludW91cygKICAgIGxpbWl0cyA9IGMoMCwgMC40KSwKICAgIGJyZWFrcyA9IGMoMCwgMC4zKSwKICAgIG5hbWUgPSAiRWZmZWN0IHNpemUiCiAgKSArCiAgZ2VvbV92bGluZSgKICAgIHhpbnRlcmNlcHQgPSAwLAogICAgY29sb3IgPSAiYmxhY2siLAogICAgbGluZXR5cGUgPSAiZGFzaGVkIgogICkgKwogIGZhY2V0X2dyaWQoCiAgICBjb2xzID0gdmFycyhwYXJhbWV0ZXIpLCByb3dzID0gdmFycyhsYWJlbCksCiAgICBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMjMpLAogICAgc2NhbGVzID0gImZyZWUiLAogICAgc3BhY2UgPSAiZnJlZSIKICApICsKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgc2l6ZSA9IDEwLCBtYXJnaW4gPSBtYXJnaW4odCA9IDE1LCByID0gMTUsIGIgPSAxNSwgbCA9IDE1KSksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gTlVMTCwgbGluZXR5cGUgPSAiYmxhbmsiLCBmaWxsID0gImdyYXk5MCIpLAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgcGFuZWwuc3BhY2luZyA9IHVuaXQoMC41LCAibGluZXMiKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZSgpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3VyID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gInNvbGlkIiwgY29sb3IgPSAiZ3JheTk1IiksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCkKICApCgojIE1ldGFtZXRhX0ZpZ1MyX21hbGUuc2lnCmBgYAoKIyMjIDEwICUgUGVyYyBzZXggZGlmZmVyZW5jZSwgbWFsZSBiaWFzClJlc3RydWN0dXJlIGRhdGEgZm9yIHBsb3R0aW5nIDogTWFsZSBiaWFzZWQsIDEwJSBkaWZmZXJlbmNlCgpgYGB7cn0Kb3ZlcmFsbDNTLnBlcmMgPC0gZ2F0aGVyKG92ZXJhbGwubWFsZS5wbG90My5wZXJjLCBwYXJhbWV0ZXIsIHZhbHVlLCBjKGxuQ1ZSLCBsblZSLCBsblJSKSwgZmFjdG9yX2tleSA9IFRSVUUpICMgbG5WUiwKCmxuQ1ZSLmNpIDwtIG92ZXJhbGwzUy5wZXJjICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuQ1ZSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuQ1ZSX2xvd2VyLCBjaS5oaWdoID0gbG5DVlJfdXBwZXIpCmxuVlIuY2kgPC0gb3ZlcmFsbDNTLnBlcmMgJT4lCiAgZmlsdGVyKHBhcmFtZXRlciA9PSAibG5WUiIpICU+JQogIG11dGF0ZShjaS5sb3cgPSBsblZSX2xvd2VyLCBjaS5oaWdoID0gbG5WUl91cHBlcikKbG5SUi5jaSA8LSBvdmVyYWxsM1MucGVyYyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJsblJSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuUlJfbG93ZXIsIGNpLmhpZ2ggPSBsblJSX3VwcGVyKQoKb3ZlcmFsbDRTLm1hbGUucGVyYyA8LSBiaW5kX3Jvd3MobG5DVlIuY2ksIGxuVlIuY2ksIGxuUlIuY2kpICU+JSBzZWxlY3QoR3JvdXBpbmdUZXJtLCBwYXJhbWV0ZXIsIHZhbHVlLCBjaS5sb3csIGNpLmhpZ2gpICMgbG5WUi5jaSwKCm92ZXJhbGw0Uy5tYWxlLnBlcmMkbGFiZWwgPC0gIlNleCBkaWZmZXJlbmNlIGluIG0vZiByYXRpb3MgPiAxMCUiCgpvdmVyYWxsNFMubWFsZS5wZXJjJHZhbHVlIDwtIGFzLm51bWVyaWMob3ZlcmFsbDRTLm1hbGUucGVyYyR2YWx1ZSkKb3ZlcmFsbDRTLm1hbGUucGVyYyRjaS5sb3cgPC0gYXMubnVtZXJpYyhvdmVyYWxsNFMubWFsZS5wZXJjJGNpLmxvdykKb3ZlcmFsbDRTLm1hbGUucGVyYyRjaS5oaWdoIDwtIGFzLm51bWVyaWMob3ZlcmFsbDRTLm1hbGUucGVyYyRjaS5oaWdoKQpgYGAKClBsb3QgRmlnUzIgIGFsbCA+MTAlIGRpZmZlcmVuY2UgKG1hbGUgYmlhcykKCmBgYHtyfQpNZXRhbWV0YV9GaWdTMl9tYWxlLnBlcmMgPC0gb3ZlcmFsbDRTLm1hbGUucGVyYyAlPiUgIyBmaWx0ZXIoLiwgR3JvdXBpbmdUZXJtICE9ICJIZWFyaW5nIikgJT4lCiAgZ2dwbG90KGFlcyh5ID0gR3JvdXBpbmdUZXJtLCB4ID0gdmFsdWUpKSArCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKAogICAgeG1pbiA9IGNpLmxvdywKICAgIHhtYXggPSBjaS5oaWdoCiAgKSwKICBoZWlnaHQgPSAwLjEsIHNob3cubGVnZW5kID0gRkFMU0UKICApICsKICBnZW9tX3BvaW50KGFlcygKICAgIHNoYXBlID0gcGFyYW1ldGVyLAogICAgZmlsbCA9IHBhcmFtZXRlcgogICksCiAgY29sb3IgPSAibWVkaXVtYXF1YW1hcmluZSIsIHNpemUgPSAyLjIsCiAgc2hvdy5sZWdlbmQgPSBGQUxTRQogICkgKwogIHNjYWxlX3hfY29udGludW91cygKICAgIGxpbWl0cyA9IGMoLTAuMiwgMC42MiksCiAgICBicmVha3MgPSBjKDAsIDAuMyksCiAgICBuYW1lID0gIkVmZmVjdCBzaXplIgogICkgKwogIGdlb21fdmxpbmUoCiAgICB4aW50ZXJjZXB0ID0gMCwKICAgIGNvbG9yID0gImJsYWNrIiwKICAgIGxpbmV0eXBlID0gImRhc2hlZCIKICApICsKICBmYWNldF9ncmlkKAogICAgY29scyA9IHZhcnMocGFyYW1ldGVyKSwgcm93cyA9IHZhcnMobGFiZWwpLAogICAgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDIzKSwKICAgIHNjYWxlcyA9ICJmcmVlIiwKICAgIHNwYWNlID0gImZyZWUiCiAgKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoCiAgICBzdHJpcC50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAyNzAsIHNpemUgPSAxMCwgbWFyZ2luID0gbWFyZ2luKHQgPSAxNSwgciA9IDE1LCBiID0gMTUsIGwgPSAxNSkpLAogICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSBOVUxMLCBsaW5ldHlwZSA9ICJibGFuayIsIGZpbGwgPSAiZ3JheTkwIiksCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgwLjUsICJsaW5lcyIpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKCksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAic29saWQiLCBjb2xvdXIgPSAiZ3JheTk1IiksCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUobGluZXR5cGUgPSAic29saWQiLCBjb2xvciA9ICJncmF5OTUiKSwKICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE0KSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKQogICkKCiMgTWV0YW1ldGFfRmlnUzJfbWFsZS5wZXJjIChGaWd1cmUgNUQgcmlnaHQgcGFuZWwpCmBgYAoKUmVzdHJ1Y3R1cmUgZGF0YSBmb3IgcGxvdHRpbmc6IApGZW1hbGUgYmlhcywgMTAgcGVyY2VudCBkaWZmZXJlbmNlLCBpbmNsdWRpbmcgVlIKCmBgYHtyfQpvdmVyYWxsM1MucGVyYyA8LSBnYXRoZXIob3ZlcmFsbC5wbG90My5wZXJjLCBwYXJhbWV0ZXIsIHZhbHVlLCBjKGxuQ1ZSLCBsblZSLCBsblJSKSwgZmFjdG9yX2tleSA9IFRSVUUpICMgbG5WUiwKCmxuQ1ZSLmNpIDwtIG92ZXJhbGwzUy5wZXJjICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImxuQ1ZSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuQ1ZSX2xvd2VyLCBjaS5oaWdoID0gbG5DVlJfdXBwZXIpCmxuVlIuY2kgPC0gb3ZlcmFsbDNTLnBlcmMgJT4lCiAgZmlsdGVyKHBhcmFtZXRlciA9PSAibG5WUiIpICU+JQogIG11dGF0ZShjaS5sb3cgPSBsblZSX2xvd2VyLCBjaS5oaWdoID0gbG5WUl91cHBlcikKbG5SUi5jaSA8LSBvdmVyYWxsM1MucGVyYyAlPiUKICBmaWx0ZXIocGFyYW1ldGVyID09ICJsblJSIikgJT4lCiAgbXV0YXRlKGNpLmxvdyA9IGxuUlJfbG93ZXIsIGNpLmhpZ2ggPSBsblJSX3VwcGVyKQoKb3ZlcmFsbDRTLnBlcmMgPC0gYmluZF9yb3dzKGxuQ1ZSLmNpLCBsblZSLmNpLCBsblJSLmNpKSAlPiUgc2VsZWN0KEdyb3VwaW5nVGVybSwgcGFyYW1ldGVyLCB2YWx1ZSwgY2kubG93LCBjaS5oaWdoKQoKb3ZlcmFsbDRTLnBlcmMkbGFiZWwgPC0gIlNleCBkaWZmZXJlbmNlIGluIG0vZiByYXRpb3MgPiAxMCUiCgpvdmVyYWxsNFMucGVyYyR2YWx1ZSA8LSBhcy5udW1lcmljKG92ZXJhbGw0Uy5wZXJjJHZhbHVlKQpvdmVyYWxsNFMucGVyYyRjaS5sb3cgPC0gYXMubnVtZXJpYyhvdmVyYWxsNFMucGVyYyRjaS5sb3cpCm92ZXJhbGw0Uy5wZXJjJGNpLmhpZ2ggPC0gYXMubnVtZXJpYyhvdmVyYWxsNFMucGVyYyRjaS5oaWdoKQpgYGAKClBsb3QgRmlnNUQgYWxsID4xMCUgZGlmZmVyZW5jZSAoZmVtYWxlKQoKYGBge3J9Ck1ldGFtZXRhX0ZpZzNTX2ZlbWFsZS5wZXJjIDwtIG92ZXJhbGw0Uy5wZXJjICU+JQogIGdncGxvdChhZXMoeSA9IEdyb3VwaW5nVGVybSwgeCA9IHZhbHVlKSkgKwogIGdlb21fZXJyb3JiYXJoKGFlcygKICAgIHhtaW4gPSBjaS5sb3csCiAgICB4bWF4ID0gY2kuaGlnaAogICksCiAgaGVpZ2h0ID0gMC4xLCBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBwYXJhbWV0ZXIpLAogICAgZmlsbCA9ICJzYWxtb24xIiwgY29sb3IgPSAic2FsbW9uMSIsIHNpemUgPSAyLjIsCiAgICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCgogICMgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9CgogIHNjYWxlX3hfY29udGludW91cygKICAgIGxpbWl0cyA9IGMoLTAuNTMsIDAuMiksCiAgICBicmVha3MgPSBjKC0wLjMsIDApLAogICAgbmFtZSA9ICJFZmZlY3Qgc2l6ZSIKICApICsKICBnZW9tX3ZsaW5lKAogICAgeGludGVyY2VwdCA9IDAsCiAgICBjb2xvciA9ICJibGFjayIsCiAgICBsaW5ldHlwZSA9ICJkYXNoZWQiCiAgKSArCiAgZmFjZXRfZ3JpZCgKICAgIGNvbHMgPSB2YXJzKHBhcmFtZXRlciksICMgcm93cyA9IHZhcnMobGFiZWwpLAogICAgIyBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMjMpLAogICAgc2NhbGVzID0gImZyZWUiLAogICAgc3BhY2UgPSAiZnJlZSIKICApICsKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgc2l6ZSA9IDEwLCBtYXJnaW4gPSBtYXJnaW4odCA9IDE1LCByID0gMTUsIGIgPSAxNSwgbCA9IDE1KSksCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG91ciA9IE5VTEwsIGxpbmV0eXBlID0gImJsYW5rIiwgZmlsbCA9ICJncmF5OTAiKSwKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIHBhbmVsLnNwYWNpbmcgPSB1bml0KDAuNSwgImxpbmVzIiksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG91ciA9ICJncmF5OTUiKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJzb2xpZCIsIGNvbG9yID0gImdyYXk5NSIpLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTQpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpCiAgKQoKIyBNZXRhbWV0YV9GaWczU19mZW1hbGUucGVyYyAoRmlndXJlIDVEIGxlZnQgcGFuZWwpCmBgYAoKRmlndXJlIFMyIAoKYGBge3J9CkZpZ1MyYyA8LSBnZ2FycmFuZ2UoTWV0YW1ldGFfRmlnUzJfZmVtYWxlLnNpZywgTWV0YW1ldGFfRmlnUzJfbWFsZS5zaWcsCiAgbmNvbCA9IDIsIG5yb3cgPSAxLCB3aWR0aHMgPSBjKDEsIDEuMjApLCBoZWlnaHRzID0gYygxLCAxKQopCgpGaWdTMmQgPC0gZ2dhcnJhbmdlKE1ldGFtZXRhX0ZpZzNTX2ZlbWFsZS5wZXJjLCBNZXRhbWV0YV9GaWdTMl9tYWxlLnBlcmMsCiAgbmNvbCA9IDIsIG5yb3cgPSAxLCB3aWR0aHMgPSBjKDEsIDEuMjApLCBoZWlnaHRzID0gYygxLCAxKQopCgojIGVuZCBjb21iaW5hdGlvbiBGaWd1cmUgNQoKRmlnUzIgPC0gZ2dhcnJhbmdlKG1hbGViaWFzX0ZpZ1MyX3NpZ3RyYWl0cywgbWFsZWJpYXNfRmlnUzJfb3ZlcjEwLCBGaWdTMmMsIEZpZ1MyZCwgbmNvbCA9IDEsIG5yb3cgPSA0LCBoZWlnaHRzID0gYygyLjIsIDIsIDIuMiwgMiksIGxhYmVscyA9IGMoIkEiLCAiICIsICJCIiwgIiAiKSkKRmlnUzIKYGBgCgojIyBBY2tub3dsZWRnZW1lbnRzCnRiZAoKIyMgUiBTZXNzaW9uIEluZm9ybWF0aW9uCgpgYGB7cn0Kc2Vzc2lvbkluZm8oKQpgYGAKCg==